動かざることバグの如し

近づきたいよ 君の理想に

Nodejsのasyncでリトライを行いたいなら「async-retry」

環境

  • nodejs v10

やりたいこと

例えばあるURLへHTTPリクエストして、失敗した場合にリトライしたい。けど失敗したときのレスポンスコードが500のときはやり直すけど、404のときは無駄なのでそのままエラーにしたい。

いいライブラリがないか探していたところ、。いくつかあって、IndigoUnited/node-promise-retry とかsindresorhus/p-retryがあったが、今回はasync-retryに決めた。理由として。ソースがシンプルなのと、zeit製ってあたり。

インストール

yarn add async-retry
yarn add node-fetch

コード

node-fetchはただのサンプル

const retry = require('async-retry');
const fetch = require('node-fetch');

(async () => {

  await retry(async bail => {
    // const res = await fetch('https://httpbin.org/status/200');
    const res = await fetch('https://httpbin.org/status/500');

    if (res.status === 404) {
      bail(new Error('404 error'));
      return;
    }

    if (res.status !== 200) {
      throw new Error('status error');
    }
  
    console.log(await res.statusText);
  }, {
    retries: 2,
    onRetry: (err, num) => {
      console.log(err, num);
    }

  })

})();

ポイントは

bail(new Error('404 error'));

で、これでリトライせずにエラー吐きつつ終了、となる。

実行結果

実行成功時

$ node index.js 
OK

実行失敗時

2回リトライしてエラーをThrowしているのがわかる。ここでややこしいのがretriesに指定するのは「初回失敗時以降何回再チャレンジするか」の値なので、初回含め合計3回リクエストが実行される。

$ node index.js 
Error: status error
    at retry (/tmp/retry_sample/index.js:20:13)
    at process._tickCallback (internal/process/next_tick.js:68:7) 1
Error: status error
    at retry (/tmp/retry_sample/index.js:20:13)
    at process._tickCallback (internal/process/next_tick.js:68:7) 2
(node:72271) UnhandledPromiseRejectionWarning: Error: status error
    at retry (/tmp/retry_sample/index.js:20:13)
    at process._tickCallback (internal/process/next_tick.js:68:7)
(node:72271) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:72271) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.