在 Nodejs 中等待並重試

在其他程式語言中,例如 Java、Ruby 和 Python,有 Thread.sleep()sleeptime.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