【问题标题】:Retry on Javascript.Promise.reject a limited number of times or until success重试 Javascript.Promise.reject 有限次数或直到成功
【发布时间】:2017-02-24 14:41:09
【问题描述】:

我有一个从客户端调用的函数 myMainFunction,然后又调用 mypromisified 函数。

场景: mypromisified 函数可能会间歇性失败,我需要延迟调用此函数(以指数增长),直到成功或达到最大尝试次数。

我目前所拥有的

下面的代码说明了我的场景并重复自己直到成功,但它会无限期地尝试,直到达到一定的计数

// called once from the client
myMainFuntion();

function rejectDelay(delay, reason) {
   // call main function at a delayed interval until success 
   // but would want to call this only a limited no of times
    setTimeout(() => {
      myMainFuntion(); // calling main function again here but with a delay
    }, delay);
}


function myMainFuntion() {
  var delay = 100;
  var tries = 3;
  tryAsync().catch(rejectDelay.bind(null, delay));
}

function tryAsync() {
  return new Promise(function(resolve, reject) {
    var rand = Math.random();
    console.log(rand);
    if (rand < 0.8) {
      reject(rand);
    } else {
      resolve();
    }
  });

}

rejectDelay 内的while 循环肯定不会工作,因为即使在 setInterval 中的实际函数执行之前,计数器也会增加,所以不确定如何解决这个问题?所以...

我试过promisifyingsetInterval 这样的东西知道它会失败:( 因为它不会减少计数器,但也不知道如何让它正确。

function rejectDelay(delay, maximumTries, reason) {
  return new Promise(function (resolve, reject) {
    console.log(tries + ' remaining');
    if (--maximumTries > 0) {
      setTimeout(function() {
        foo();
      }, 500);
    } 
  });
}
function myMainFunction() {
  var delay = 100;
  var maximumTries = 3;
  tryAsync().catch(rejectDelay.bind(null, delay, maximumTries));
}

【问题讨论】:

标签: javascript es6-promise


【解决方案1】:

使用我经常使用的几个辅助函数,这变得非常容易

“帮手”

Promise.wait = (time) => new Promise(resolve => setTimeout(resolve, time || 0));
Promise.retry = (cont, fn, delay) => fn().catch(err => cont > 0 ? Promise.wait(delay).then(() => Promise.retry(cont - 1, fn, delay)) : Promise.reject('failed'));

代码:

function myMainFuntion() {
      var delay = 100;
      var tries = 3;
      Promise.retry(tries, tryAsync, delay);
}

帮助程序的 ES5 版本

Promise.wait = function (time) {
    return new Promise(function (resolve) {
        return setTimeout(resolve, time || 0);
    });
};
Promise.retry = function (cont, fn, delay) {
    return fn().catch(function (err) {
        return cont > 0 ? Promise.wait(delay).then(function () {
            return Promise.retry(cont - 1, fn, delay);
        }) : Promise.reject('failed');
    });
};

【讨论】:

  • 非常感谢您提供简洁的解决方案:)。我了解在 retry 上进行的递归调用,但无法理解等待功能 -> 我看到您正在返回一个新的 Promise,但没有明确解决或拒绝相同的问题? - 在我看来,这意味着Promise.wait() 上的.then 永远不会被调用?你介意再给我解释一下吗?提前谢谢你 PS:我知道它是从我在这里制作到jsfiddle.net/jayas_godblessall/j50u8br9 的盗版中工作的 - 但如前所述 - 在我的脑海中不起作用:(
  • setTimeout 的第一个参数是要运行的函数...它设置为resolve ...因此在time ms 之后调用resolve
  • 很好的 Promise.retry 递归定义!请注意,函数“fn”实际上会在此处被调用“cont”+1 次,除非您将 cont 与 1 进行比较。
  • 看你怎么想重试我猜
【解决方案2】:

一种稍微不同的方法,它使用“异步递归”在返回承诺的函数中调用嵌套函数:

function retry( func, maxTries, delay) {
    var reTry = 0;
    return new Promise( function(resolve, reject) {
        function callFunc() {
          try
          {
              func().then(resolve, function( reason) {
                  if( ++reTry >= maxTries) {
                      reject( reason);
                  }
                  else {
                      setTimeout( callFunc,
                         typeof delay=="function" ? delay( retry) : delay );
                  }
              });
          }
          catch(e) {
              reject(e);
          }
        }
        callFunc();      
    });
}

//  ******* run snippet to test ********


var retryCount = 0;
function getDelay( n) {
//    return 100 * n*n + 500; // for example
      ++ retryCount;
      return 100;  // for testing

}

function testFunc() {
    return Math.random() < 0.8 ? Promise.reject("too many tries") : Promise.resolve( "success");
}

retry( testFunc, 5, getDelay).then(
 function(data) { console.log("data: %s, retryCount %s", data, retryCount);},
 function(reason){console.log("reason: %s, retryCount %s", reason, retryCount);}
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-08
    相关资源
    最近更新 更多