Skip to content

Instantly share code, notes, and snippets.

@tryggvigy
Last active March 6, 2020 18:18
Show Gist options
  • Save tryggvigy/55b864394d8cff71f5cbb0de4aa90808 to your computer and use it in GitHub Desktop.
Save tryggvigy/55b864394d8cff71f5cbb0de4aa90808 to your computer and use it in GitHub Desktop.
Promise retries with exponential backoff
// paste this in any JS REPL to see the execution!
// Note that the fakeAPI is simulated to be flaky so try executin this a few times
// to see both the success and failure case
(() => {
/**
* Wrap a promise API with a function that will attempt the promise over and over again
* with exponential backoff until it resolves or reaches the maximum number of retries.
* - First retry: 500 ms + <random> ms
* - Second retry: 1000 ms + <random> ms
* - Third retry: 2000 ms + <random> ms
* and so forth until maximum retries are met, or the promise resolves.
*/
const withRetries = ({ attempt, maxRetries }) => async (...args) => {
const slotTime = 500;
let retryCount = 0;
do {
try {
console.log('Attempting...', Date.now());
return await attempt(...args);
} catch (error) {
const isLastAttempt = retryCount === maxRetries;
if (isLastAttempt) return Promise.reject(error);
}
const randomTime = Math.floor(Math.random() * slotTime);
const delay = 2 ** retryCount * slotTime + randomTime;
// Wait for the exponentially increasing delay period before retrying again.
await new Promise(resolve => setTimeout(resolve, delay));
} while (retryCount++ < maxRetries);
}
const fakeAPI = (...args) => Math.random() < 0.25 ? Promise.resolve(args) : Promise.reject(new Error('fakeAPI failure'))
const fakeAPIWithRetries = withRetries({ attempt: fakeAPI, maxRetries: 3 });
fakeAPIWithRetries('arg1', 'arg2').then((result) => console.log(result))
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment