javascript - promise 重试设计模式

标签 javascript node.js promise

编辑

  1. 在 promise 解决之前不断重试的模式(使用 delaymaxRetries)。
  2. 不断重试直到条件满足的模式 满足结果(使用 delaymaxRetries)。
  3. 一种内存高效的动态模式,可无限重试(提供延迟)。

#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/

相关文章:

javascript - 显示 Promise 错误消息但未捕获错误

node.js - 如何最好地使对待 promise 拒绝像未捕获的异常一样?

javascript - 将 JavaScript 事件附加到 AJAX 加载的搜索结果列表的最佳方法是什么?

javascript - twilio 发送短信在 meteor 中不起作用

javascript - 范围错误 : Invalid time value

javascript - 在本地文件上使用 jQuery 的 "load"方法

javascript - 检测是否支持事件监听器

javascript - RJS 是邪恶的吗?为什么?

javascript - 句号、单词和冒号的正则表达式

javascript - 获取 JavaScript promise 值