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