当前位置: 首页 > 知识库问答 >
问题:

promise重试设计模式

宇文航
2023-03-14

编辑

  1. 继续重试直到promise解决的模式(具有延迟和最大重试次数)

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

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

共有3个答案

左丘季
2023-03-14

提到了许多好的解决方案,现在使用async/wait可以轻松解决这些问题。

如果你不介意递归方法,那么这就是我的解决方案。

function retry(fn, retries=3, err=null) {
  if (!retries) {
    return Promise.reject(err);
  }
  return fn().catch(err => {
      return retry(fn, (retries - 1), err);
    });
}
张勇
2023-03-14

2.不断重试直到结果满足条件的模式(具有延迟和最大重试次数)

这是一种以递归方式处理本机promise的好方法:

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。

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

陆啸
2023-03-14

有点不同的东西...

异步重试可以通过构建来实现。catch()链,与更常见的相反。然后()链。

这种方法是:

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

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

首先,要用作<代码>的效用函数。catch()回调。

var t = 500;

function rejectDelay(reason) {
    return new Promise(function(resolve, reject) {
        setTimeout(reject.bind(null, reason), t); 
    });
}

现在,您可以非常简洁地构建捕捉链:

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()可以是同步或异步的。

添加进一步的测试也很简单。只需在两个渔获量之间夹一条鱼链。

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

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

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

 类似资料:
  • 问题内容: 编辑 继续重试直到承诺解决的模式(带有delay和maxRetries)。 在结果满足条件之前一直重试的模式(带有delay和maxRetries)。 具有无限重试次数(提供延迟)的高效内存动态模式。 #1的代码。 继续重试,直到承诺解决为止(该语言是否有任何改进社区?) 采用 #2的代码会 继续重试,直到条件以可重用的方式满足条件为止(条件会有所不同)。 问题答案: 有点不同… 异步

  • 问题内容: 我正在编写一些重新连接逻辑,以定期尝试建立与发生故障的远程端点的连接。本质上,代码如下所示: 我已经在很多情况下使用类似于上面的代码解决了这个普遍的问题,但是我对结果不满意。是否有设计用于解决此问题的设计模式? 问题答案: 值得结帐的一个库是Sarge,它会根据已定义的计划自动执行重试。

  • 主要内容:1.策略模式,2.模板方法,3.观察者模式,4.责任链/职责链模式java8中提供的很多新特性可以用来重构传统设计模式中的写法 1.策略模式 上图是策略模式的类图,假设我们现在要保存订单,接口定义要做什么,而以及则提供了二种策略,分别是保存到数据库,以及传统的关系型数据库,最后在中通过构造函数注入最终要使用的策略。 OrderService接口 Mysql策略实现 Nosql策略实现 使用策略的辅助"容器" 运行测试类 重构后,可以省去2个策略实现类 2.模板方

  • 各大设计模式例子参考:CSDN专栏 . C++ 设计模式 系列博文 设计模式工程目录 单例模式 单例模式例子 抽象工厂模式 抽象工厂模式例子 适配器模式 适配器模式例子 桥接模式 桥接模式例子 观察者模式 观察者模式例子 设计模式的六大原则 单一职责原则(SRP,Single Responsibility Principle) 里氏替换原则(LSP,Liskov Substitution Prin

  • 一、概述 二、创建型 1. 单例(Singleton) 2. 简单工厂(Simple Factory) 3. 工厂方法(Factory Method) 4. 抽象工厂(Abstract Factory) 5. 生成器(Builder) 6. 原型模式(Prototype) 三、行为型 1. 责任链(Chain Of Responsibility) 2. 命令(Command) 3. 解释器(Int

  • 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。 本教程将通过 Java 实例,一步一步向您讲解设计模式的概念。 现在开始学习设计模式! 谁适合阅读本教程? 无论您是新手,还是老手,本教程都值得一读。对于那些