Created
February 15, 2018 00:27
-
-
Save selfcontained/5ecd71f3338287994a827ea43ee3daef to your computer and use it in GitHub Desktop.
Promise Throttler for Async Function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Example refreshAuth fn that might call Google | |
function refreshAuth (oldToken, done) { | |
console.log('actually refreshing the old token', oldToken) | |
setTimeout(() => { | |
done(null, getNewToken()) | |
}, 2000) | |
} | |
// Pretend we're issuing new tokens | |
let token = 1 | |
function getNewToken () { | |
return token++ | |
} | |
// Pretty generic module to throttle an async function | |
function promiseThrottler (myAsyncFn) { | |
let activePromise = null | |
// return a wrapper to make sure only one person calls refreshAuthFn at a time | |
return function (...args) { | |
console.log('promise throttler wrapper') | |
let done = args.pop() | |
// No active promise, create one | |
if (!activePromise) { | |
console.log('creating promise') | |
// Setup promise, call refreshAuth fn and resolve or reject based on response | |
activePromise = new Promise((resolve, reject) => { | |
// Define a callback for when we actually call myAsyncFn | |
let myAsyncFnCallback = (err, ...response) => { | |
// Reject the promise, and pass along the error and response | |
if (err) { | |
return reject(err) | |
} | |
// Resolve the promise and pass along arguments (not error) | |
resolve(response) | |
} | |
// Kick off refreshAuth call here passing along args and a callback to resolve/reject promise | |
myAsyncFn.apply(null, args.concat([myAsyncFnCallback])) | |
}) | |
} | |
// Wait for promise to resolve, and call done callback | |
activePromise | |
.then(resultArgs => { | |
// call done with a null error and rest of args | |
done(null, ...resultArgs) | |
}) | |
.catch(err => { | |
done(err) | |
}) | |
// Poor mans Promise.finally() | |
.then(() => { | |
activePromise = null | |
}) | |
} | |
} | |
// You could use this in another place like so: | |
let throttledRefreshAuth = promiseThrottler(refreshAuth) | |
let myToken = getNewToken() | |
function gotNewToken (err, newToken) { | |
if (err) { | |
return console.error('error refreshing tokne: ', err) | |
} | |
myToken = newToken | |
console.log('new token: ', newToken) | |
} | |
throttledRefreshAuth(myToken, gotNewToken) | |
throttledRefreshAuth(myToken, gotNewToken) | |
throttledRefreshAuth(myToken, gotNewToken) | |
// This should get handled in the first round of refreshes | |
setTimeout(() => { | |
throttledRefreshAuth(myToken, gotNewToken) | |
}, 1000) | |
// Wait awhile and grab more new tokens | |
setTimeout(() => { | |
console.log('something comes along later to refresh the token...') | |
throttledRefreshAuth(myToken, gotNewToken) | |
throttledRefreshAuth(myToken, gotNewToken) | |
}, 5000) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment