承诺重试设计模式

新手上路,请多包涵

编辑

  1. 不断重试直到承诺解决的模式(使用 delaymaxRetries )。
  2. 不断重试直到条件满足结果的模式(使用 delaymaxRetries )。
  3. 具有无限重试的内存高效动态模式( delay 提供)。

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

原文由 user2727195 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 318
2 个回答

有点不同……

异步重试可以通过构建 .catch() 链来实现,而不是更常见的 .then() 链。

这种方法是:

  • 只有指定的最大尝试次数才有可能。 (链条必须是有限长度的),
  • 仅建议使用较低的最大值。 (Promise 链消耗的内存大致与其长度成正比)。

否则,使用递归解决方案。

首先,一个实用函数用作 .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);

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

演示https ://jsfiddle.net/duL0qjqe/3/


所有版本都设计为 attempt 是一个返回承诺的异步函数。它也可以想象地返回一个值,在这种情况下,链将沿着它的成功路径到达下一个/终端 .then()

原文由 Roamer-1888 发布,翻译遵循 CC BY-SA 3.0 许可协议

2. 不断重试直到结果满足条件的模式(延迟和 maxRetries)

这是以递归方式使用本机承诺执行此操作的好方法:

 const wait = ms => new Promise(r => setTimeout(r, ms));

const retryOperation = (operation, delay, retries) => new Promise((resolve, reject) => {
  return operation()
    .then(resolve)
    .catch((reason) => {
      if (retries > 0) {
        return wait(delay)
          .then(retryOperation.bind(null, operation, delay, retries - 1))
          .then(resolve)
          .catch(reject);
      }
      return reject(reason);
    });
});

这就是你如何称呼它,假设 func 有时成功有时失败,总是返回一个我们可以记录的字符串:

 retryOperation(func, 1000, 5)
  .then(console.log)
  .catch(console.log);

在这里,我们调用 retryOperation 要求它每秒重试一次,最大重试次数 = 5。

如果你想要没有承诺的更简单的东西,RxJs 会帮助你: https ://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/retrywhen.md

原文由 Yair Kukielka 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题