javascript – 承诺重试设计模式

编辑

>继续重试的模式,直到承诺结算(延迟和
maxRetries).
>继续重试直到条件的模式
满足结果(延迟和
maxRetries).
>具有无限重试的内存高效动态模式(提供延迟).

代码为#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的代码继续重试,直到条件满足,然后以可重用的方式结果(条件是变化的).

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);

DEMO: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.

p = p.catch(attempt).then(test1).then(test2).then(test3).catch(rejectDelay);

DEMO:https://jsfiddle.net/duL0qjqe/3/

所有版本都旨在尝试成为一个承诺返回异步函数.它也可以设想返回一个值,在这种情况下,链将跟随其成功路径到下一个/终端.then().

相关文章

最后的控制台返回空数组.控制台在ids.map函数完成之前运行va...
我正在尝试将rxJava与我已经知道的内容联系起来,特别是来自J...
config.jsconstconfig={base_url_api:"https://douban....
我正在阅读MDN中的javascript,并且遇到了这个谈论承诺并且不...
config.jsconstconfig={base_url_api:"https://douban....
这是我的代码main.cpp:#include<string>#include<...