[解決済み] プロミス・リトライ・デザインパターン
2023-02-17 10:13:39
質問
編集
-
プロミスが解決するまでリトライし続けるパターン(
delay
とmaxRetries
). -
結果が条件を満たすまでリトライし続けるパターン。
というパターンがあります。
delay
とmaxRetries
). -
無制限に再試行できるメモリ効率の良いダイナミックパターン (
delay
が提供されます)。
1のコードです。 promiseが解決するまでリトライし続ける(言語などの改善コミュニティは?)
Promise.retry = function(fn, times, delay) {
return new Promise(function(resolve, reject){
var error;
var attempt = function() {
if (times == 0) {
reject(error);
} else {
fn().then(resolve)
.catch(function(e){
times--;
error = e;
setTimeout(function(){attempt()}, delay);
});
}
};
attempt();
});
};
使用する
work.getStatus()
.then(function(result){ //retry, some glitch in the system
return Promise.retry(work.unpublish.bind(work, result), 10, 2000);
})
.then(function(){console.log('done')})
.catch(console.error);
2のコード
が条件を満たすまでリトライし続けます。
then
の結果を再利用可能な方法で再試行します(条件は様々です)。
work.publish()
.then(function(result){
return new Promise(function(resolve, reject){
var intervalId = setInterval(function(){
work.requestStatus(result).then(function(result2){
switch(result2.status) {
case "progress": break; //do nothing
case "success": clearInterval(intervalId); resolve(result2); break;
case "failure": clearInterval(intervalId); reject(result2); break;
}
}).catch(function(error){clearInterval(intervalId); reject(error)});
}, 1000);
});
})
.then(function(){console.log('done')})
.catch(console.error);
どのように解決するのですか?
ちょっと違うかな.
非同期リトライは
.catch()
チェーンを構築することで実現できます。
.then()
チェーンとは異なります。
このやり方は.
- 指定された最大試行回数のみ可能です。(チェーンは有限の長さである必要があります)。
- は低い最大値でのみ推奨されます。(プロミス チェーンはその長さにほぼ比例してメモリを消費します)。
そうでなければ、再帰的な解決策を使用します。
まず、効用関数として
.catch()
のコールバックとして使用します。
var t = 500;
function rejectDelay(reason) {
return new Promise(function(resolve, reject) {
setTimeout(reject.bind(null, reason), t);
});
}
これで、非常に簡潔に .catch チェーンを構築することができます。
1. プロミスが解決するまでリトライする、遅延あり
var max = 5;
var p = Promise.reject();
for(var i=0; i<max; i++) {
p = p.catch(attempt).catch(rejectDelay);
}
p = p.then(processResult).catch(errorHandler);
デモ : https://jsfiddle.net/duL0qjqe/
2. 結果が何らかの条件を満たすまで、遅滞なく再試行する。
var max = 5;
var p = Promise.reject();
for(var i=0; i<max; i++) {
p = p.catch(attempt).then(test);
}
p = p.then(processResult).catch(errorHandler);
デモ : https://jsfiddle.net/duL0qjqe/1/
3. 結果が何らかの条件を満たすまで、遅延を伴って再試行する。
(1)と(2)を理解した上で、テストと遅延の組み合わせも同様に些細なことです。
var max = 5;
var p = Promise.reject();
for(var i=0; i<max; i++) {
p = p.catch(attempt).then(test).catch(rejectDelay);
// Don't be tempted to simplify this to `p.catch(attempt).then(test, rejectDelay)`. Test failures would not be caught.
}
p = p.then(processResult).catch(errorHandler);
test()
は同期でも非同期でもかまいません。
さらにテストを追加するのも簡単でしょう。2つのキャッチの間にthensの連鎖を挟むだけです。
p = p.catch(attempt).then(test1).then(test2).then(test3).catch(rejectDelay);
デモ : https://jsfiddle.net/duL0qjqe/3/
すべてのバージョンは
attempt
はプロミスを返す非同期関数であるように設計されています。この場合、チェーンはその成功経路を辿って次/終端である
.then()
.
関連
-
[解決済み] 明示的なプロミス構築のアンチパターンとそれを回避する方法とは?
-
[解決済み] .then()チェーンで以前のプロミス結果にアクセスするにはどうすればよいですか?
-
[解決済み] JavaScriptで次の要素/前の要素を取得しますか?
-
[解決済み] jqueryでdivの要素がオーバーフローしていないかチェックする
-
[解決済み] reactのrender関数でdynamic hrefを作成するには?
-
[解決済み] bootstrap のポップオーバーがすべての要素の上に表示されない
-
[解決済み] react-routerのハッシュフラグメントからクエリパラメータを取得する
-
[解決済み] $.ajax実行中にローディングイメージを表示する
-
[解決済み] javascriptのキャンバスで画像をリサイズする (スムーズ)
-
[解決済み] jQueryのバージョン1、バージョン2、バージョン3の違いは何ですか?[クローズド]
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 明示的なプロミス構築のアンチパターンとそれを回避する方法とは?
-
[解決済み] ジェスト あるクラスの特定のメソッドをモックする方法
-
[解決済み] JavaScriptで次の要素/前の要素を取得しますか?
-
[解決済み] なぜJavaScriptでは!{}[true]がtrueに評価されるのですか?
-
[解決済み] JavaScriptで文字列を数値に変換する最速の方法は何ですか?
-
[解決済み] JavaScriptでの大文字小文字を区別しない正規表現
-
[解決済み] コールバック地獄とは何か、RXはそれをどのように、そしてなぜ解決するのか?
-
[解決済み] javascriptで文字列から関数を作成する方法はありますか?
-
[解決済み] JavaScript で css プロパティを使用して HTML 要素の背景色を設定する方法
-
[解決済み] Chrome拡張機能:popup.htmlを強制終了させる