在 Nodejs 中等待并重试
在其他编程语言(例如 Java、Ruby 和 Python)中,有 Thread.sleep()
、sleep
和 time.sleep()
方法来暂停当前线程的执行,并在指定时间后等待继续执行,当与循环一起使用时,它可以帮助解决竞争条件问题等。在 node.js 和一般的 JavaScript 中,由于单线程、事件驱动和异步架构的性质,暂停和等待的方式可能看起来不是很明显,也不常见。但是,由于在某些情况下仍然需要并且有助于使用 wait
和 retry
,因此可以在 nodejs 或 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;
};
参考资料
- 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