Retry Utilities Example
Helpers for automatic retrying of sketchy processes
author(s):
Jasper Palfree @wellcaffeinated
HTML
<pre id="log"></pre>
JavaScript 1.7
// ---
// Helpers for automatic retrying of sketchy processes.
// Linear delay or exponential backoff
// Made by @wellcaffeinated
// No copyright
// ---
// Throw an instance of this in order to continue retrying
class Retry extends Error {}
// Use this to wrap a function that may fail. If the function
// throws an instance of Retry, it will be attempted again
// until it resolves or throws anything else
const withRetry = (fn, {
maxTries = false,
dt = 1000,
expBackoff = false,
maxDelay = 60000,
onRetry = null
} = {}) => async (...args) => {
let tries = 1
while (true) {
try {
return await fn.apply(this, args)
} catch (error) {
if (!(error instanceof Retry) || maxTries && tries >= maxTries) {
throw error
}
const waitTime = expBackoff ?
Math.min(maxDelay, Math.pow(2, tries - 1) * dt) :
dt
if (onRetry) { onRetry({ error, tries, waitTime }) }
tries += 1
await new Promise(resolve => setTimeout(resolve, waitTime))
}
}
}
// --- Usage examples: ---
(async () => {
const log = msg => document.getElementById('log').innerHTML += msg + '\n'
const delay = (dt = 1000) => new Promise(resolve => setTimeout(resolve, dt))
const onRetry = ({ tries, waitTime }) => log(`Attempt number ${tries} failed, waiting: ${waitTime}ms`)
let startTime
const sketchyFunction = async (msg) => {
await delay()
if ((Date.now() - startTime) <= 8000){
throw new Error('Something went wrong')
} else {
log(msg)
}
}
const linearDelay = withRetry(
(msg) => sketchyFunction(msg).catch(e => Promise.reject(new Retry)),
{ onRetry }
)
const expBackoff = withRetry(
(msg) => sketchyFunction(msg).catch(e => Promise.reject(new Retry)),
{ onRetry, expBackoff: true }
)
log('Linear delay')
startTime = Date.now()
await linearDelay("hello world")
log('Exponential backoff')
startTime = Date.now()
await expBackoff("hello again")
})()