编辑
- 在 promise 解决之前不断重试的模式(使用
delay
和maxRetries
)。 - 不断重试直到条件满足的模式
满足结果(使用
delay
和maxRetries
)。 - 一种内存高效的动态模式,可无限重试(提供
延迟
)。
#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()
链。
这种方法是:
- 只有在指定的最大尝试次数下才有可能。 (链的长度必须是有限的),
- 只建议使用较低的最大值。 (Promise 链消耗的内存大致与其长度成正比)。
否则,使用递归解决方案。
首先,一个用作.catch()
回调的实用函数。
var t = 500;
function rejectDelay(reason) {
return new Promise(function(resolve, reject) {
setTimeout(reject.bind(null, reason), t);
});
}
现在您可以非常简洁地构建 .catch 链:
1.重试直到 promise 解决,延迟
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()
可以是同步的也可以是异步的。
添加进一步的测试也很简单。只需将一串thens夹在两个catch之间即可。
p = p.catch(attempt).then(test1).then(test2).then(test3).catch(rejectDelay);
演示:https://jsfiddle.net/duL0qjqe/3/
所有版本都是为 attempt
设计为返回 promise 的异步函数。它也可以想象返回一个值,在这种情况下,链将沿着其成功路径到达下一个/终端 .then()
。
关于javascript - promise 重试设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38213668/