環境
- 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.