在 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