Nodejs で待機して再試行する

Java、Ruby、Python などの他のプログラミング言語には、現在のスレッドの実行を一時停止し、指定された時間後に実行を続行する Thread.sleep()sleep、および time.sleep() メソッドがあり、ループと一緒に使用すると、たとえば競合状態の問題に対処するのに役立ちます。node.js、および一般的な JavaScript では、シングルスレッド、イベント駆動型、および非同期アーキテクチャの性質上、一時停止して待機する方法はあまり明白ではなく、頻繁に見られるようには見えない場合があります。ただし、特定の状況では waitretry の使用が依然として必要であり、役立つため、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;
};

参考文献

nodejs