编辑
#1的代码。 继续重试,直到承诺解决为止(该语言是否有任何改进社区?)
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以可重用的方式满足条件为止(条件会有所不同)。
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()
.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);
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);
3.重试直到结果满足一定条件,然后延迟
考虑到(1)和(2)之后,组合的test + delay同样是微不足道的。
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() 可以是同步或异步的。
test()
添加更多测试也将是微不足道的。只需在两个鱼钩之间夹上一串炸薯条即可。
p = p.catch(attempt).then(test1).then(test2).then(test3).catch(rejectDelay);
所有版本均设计为attempt可返回承诺的异步功能。还可以想象它返回一个值,在这种情况下,链将遵循其成功路径到达next / terminal.then()。
attempt