promises-retry
Version:
Retry promises with exponential back-off strategy. Exit on custom logic before the maximum number of retries.
50 lines (46 loc) • 1.81 kB
JavaScript
/**
* @typedef {Object} retryOptions
* @property {Number} retries The maximum amount of times to retry the operation. Default is 5.
* @property {Number} factor The exponential factor to use. Default is 2.
* @property {Number} minTimeout The number of milliseconds before starting a retry. Default is 1000.
* @property {function(attempt,Error):Boolean} exit Function to determine if retries should not continue any further. By default this function returns false if another one is not specified in options.
*/
/**
* Helper to provide easy retry for a function which returns a promise
* @param {Function} fn anonymus function wrapper for a function that returns a promise
* @param {retryOptions} options retry options
*/
async function retry(fn, options) {
const opts = Object.assign({}, {
retries: 5,
factor: 2,
minTimeout: 1000,
exit: (attempt, err) => { return false }
}, options || {});
for (let i = 0; i < opts.retries; i++) {
try {
return await fn();
} catch (err) {
const currentAttempt = i + 1;
err.retry = {
attempts: currentAttempt
};
if (opts.exit(currentAttempt, err) === true) {
throw err;
}
const exponentialTimeout = Math.pow(opts.factor, i) * 100;
const waitTime = exponentialTimeout > opts.minTimeout ? exponentialTimeout : opts.minTimeout;
await wait(waitTime);
if (currentAttempt === opts.retries)
throw err;
}
}
}
function wait(timeout) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, timeout)
});
}
module.exports = exports = retry;