ES6 Promises を使用して、リングに帽子を投げたほうがいいと思いました...
function until_success(executor){
var before_retry = undefined;
var outer_executor = function(succeed, reject){
var rejection_handler = function(err){
if(before_retry){
try {
var pre_retry_result = before_retry(err);
if(pre_retry_result)
return succeed(pre_retry_result);
} catch (pre_retry_error){
return reject(pre_retry_error);
}
}
return new Promise(executor).then(succeed, rejection_handler);
}
return new Promise(executor).then(succeed, rejection_handler);
}
var outer_promise = new Promise(outer_executor);
outer_promise.before_retry = function(func){
before_retry = func;
return outer_promise;
}
return outer_promise;
}
executor
引数はコンストラクターに渡されるものと同じPromise
ですが、成功のコールバックをトリガーするまで繰り返し呼び出されます。このbefore_retry
関数は、失敗した試行に対するカスタム エラー処理を可能にします。真の値が返された場合、それは成功したと見なされ、「ループ」が終了し、その真の値が結果として返されます。関数が登録されていない場合before_retry
、または偽の値を返す場合、ループは別の反復のために実行されます。3 番目のオプションは、before_retry
関数自体がエラーをスローすることです。これが発生すると、「ループ」が終了し、そのエラーがエラーとして渡されます。
次に例を示します。
var counter = 0;
function task(succ, reject){
setTimeout(function(){
if(++counter < 5)
reject(counter + " is too small!!");
else
succ(counter + " is just right");
}, 500); // simulated async task
}
until_success(task)
.before_retry(function(err){
console.log("failed attempt: " + err);
// Option 0: return falsey value and move on to next attempt
// return
// Option 1: uncomment to get early success..
//if(err === "3 is too small!!")
// return "3 is sort of ok";
// Option 2: uncomment to get complete failure..
//if(err === "3 is too small!!")
// throw "3rd time, very unlucky";
}).then(function(val){
console.log("finally, success: " + val);
}).catch(function(err){
console.log("it didn't end well: " + err);
})
オプション 0 の出力:
failed attempt: 1 is too small!!
failed attempt: 2 is too small!!
failed attempt: 3 is too small!!
failed attempt: 4 is too small!!
finally, success: 5 is just right
オプション 1 の出力:
failed attempt: 1 is too small!!
failed attempt: 2 is too small!!
failed attempt: 3 is too small!!
finally, success: 3 is sort of ok
オプション 2 の出力:
failed attempt: 1 is too small!!
failed attempt: 2 is too small!!
failed attempt: 3 is too small!!
it didn't end well: 3rd time, very unlucky