Wait and retry in Nodejs
In other programming languages such as Java, Ruby and Python, there are Thread.sleep()
, sleep
, and time.sleep()
methods to pause the execution of the current thread and wait after specified time to continue the execution, and when used together with loops, it can help address race condition issues for example. In node.js, and generally JavaScript, the way to pause and wait may not seem very obvious and frequently seen due to the nature of single-threaded, event-driven, and asyncronous architecture. However, since the use of wait
and retry
is still needed and helpful under certain circumstances, it is possible to simulate similar functions and effects in nodejs or JavaScript.
How to simulate sleep
/wait
with setTimeout
- with
new Promise
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
- with
util.promisify
import util from 'node:util';
const wait = util.promisify(setTimeout);
How to implement retry
with back-off
- with
recursive
functions
const retry = async (fn, depth = 0, numRetries = 3) => {
try {
return await fn();
} catch (e) {
if (depth === numRetries) {
throw e;
}
console.log('retry...');
await wait(2 ** depth * 10);
return retry(fn, depth + 1, numRetries);
}
}
- with
for
loops
const retry = async (fn, retryDelayMs = 100, numRetries = 3) => {
for (let attempt = 0; attempt <= numRetries; attempt++) {
try {
return await fn();
} catch (e) {
if (attempt === numRetries) {
throw e;
}
console.log('retry...');
await wait(retryDelayMs);
retryDelayMs *= 2;
}
}
}
- until function returns
truthy
value
const retry = async (fn, retryDelayMs = 100, numRetries = 3) => {
let result;
for(let i = 0; i < numRetries; i++) {
try {
result = await fn();
} catch (e) {
// ignore errors
}
if(result) {
return result;
}
console.log('retry...');
await wait(retryDelayMs);
retryDelayMs *= 2;
}
return result;
};
References
- How to implement an exponential backoff retry strategy in Javascript
- Promises with Retries and Back-Off in Nodejs
- A few general patterns for retries using promises
- Add option to page.goto() to retry on ERR_CONNECTION_REFUSED #2460