こんにちは、ヘルスケア部門エンジニアの小林です。今回はJavaScript(Node.js含む)にてPromiseのリトライをどうやるかを考えてみます。
ちなみにPromiseでリトライを実現するためのパッケージはたくさんあります。ただ、リトライのためだけに余計なものも入ったパッケージを導入するのも嫌なので、担当プロダクトでは自分で実装したものを使っています。
catchをチェーンする
やりたいこと
- 処理に成功したら終了
- 処理に失敗したらやり直す
- 規定回数以上失敗したら例外
これらを実現するだけなら、Promise.prototype.catch
を必要回数分チェーンすれば実現できます。
コードで説明すると以下のようになります。
// 失敗したらリトライしたい処理 const func = () => { ... }; // 最大3回リトライ可能にする場合のPromise生成方法 const promise = Promise.reject().catch(func).catch(func).catch(func).catch(func);
- 必ず1回は実行されてほしいので、最初にわざと
reject
する- こうすることで最初の
catch
に入る
- こうすることで最初の
- 処理に成功する(例外が発生しない)と後続の
catch
はスルーされる - 処理に失敗する(例外が発生する)と直後の
catch
に入り、再度同じ処理をする - 後続に
catch
がない(規定回数リトライしてしまった)場合は例外が発生する- この後に更に
catch
をチェーンすれば例外処理が可能
- この後に更に
このコードを汎用的なメソッドにしたのが以下になります。
function retryable(retryCount, func) { let promise = Promise.reject().catch(() => func()); for (let i = 0; i < retryCount; i++) { promise = promise.catch(err => func()); } return promise; } retryable(3, () => { ... }) .catch(err => { // 例外処理 });
いかがでしょうか。
追記
stackoverflowで同様のAnswerを投稿されている方がいらっしゃいました。