如何在promise链的中间成功循环

时间:2018-02-17 09:01:28

标签: javascript node.js

我正在组建一个承诺链,这是一个新的道歉。我想要做的是,对于任何特定函数中的任何错误,我想等待一秒钟再试一次,直到成功为止,然后根据原始计划继续使用promise链。

我尝试了if语句,如果有错误消息则再次调用该函数,如果没有则解析,但是这不会继续成功的promise链。

然后我开发了一个解决方案,其中包含一个内置于该函数中的for循环,如下所示:

var firstMethod = function() {
    var promise = new Promise(function(resolve, reject){
       setTimeout(function() {
          console.log('first method completed');
          resolve();
       }, 1000);
    });
    return promise;
 };

var secondMethod = function(someStuff) {
    var promise = new Promise(function(resolve, reject){
        for(let randomNumber ; randomNumber < .9||randomNumber == null ;  )
            {   
                setTimeout(function() {
                    randomNumber = Math.random();
                    console.log('the number wasn\'t big enough');
                    if (randomNumber>.9)
                    {  
                        console.log("got a number big enough");
                        resolve();
                    }
                }, 1000)
            }
        });
    return promise;
};

var thirdMethod = function(someStuff) {
    var promise = new Promise(function(resolve, reject){
       setTimeout(function() {
          console.log('third method completed');
          resolve();
       }, 1000);
    });
    return promise;
 };

 firstMethod()
    .then(secondMethod)
    .then(thirdMethod);

它完成firstMethod,然后在我尝试运行它时挂起。如果我在secondMethod中注释掉setTimeout它可以工作,但我觉得这不是模仿我想要使用它的真实案例场景。

我哪里错了?是否有更好的方法来循环中间承诺链,直到您获得特定结果,然后继续承诺链?

2 个答案:

答案 0 :(得分:1)

您可以将 secondMethod 替换为

    quantsDescription = parser.parse(BriefDescription)
    quantsUses = parser.parse(Uses)
    quantsPeriod = parser.parse(GrowingPeriod)
    print 'BriefDescription Quant:'
    print quantsDescription
    print 'Uses Quant:' 
    print quantsUses
    print 'GrowingPeriod Quant:'
    print quantsPeriod
    for i in quantsDescription:
        print type(i[1])  # indexing the second element of the tuple?

你的代码不起作用的原因,因为停止var secondMethod = function (someStuff) { var promise = new Promise(function (resolve, reject) { let randomNumber; (function doItUntilGetEnoughBigNumber() { setTimeout(function () { randomNumber = Math.random(); if (randomNumber > .9) { console.log("got a number big enough", randomNumber); resolve(); } else { // edited: message moved her console.log('the number wasn\'t big enough', randomNumber); doItUntilGetEnoughBigNumber(); } }, 1000) })() }); return promise; }; 循环的条件是异步的,所以它会被推迟,所以for循环将永远存在。

更新不使用IIFE

for

答案 1 :(得分:0)

异步事件(例如,当setTimeout完成时)的重要之处在于不直接调用处理程序,而是将事件放入所谓的事件队列中。 javascript引擎(事件循环)接受一个接一个的事件并执行它,当它完成它需要下一个。首先,它将执行你的for循环并设置所有超时。然后当它完成并且一秒钟后,它将开始执行setTimeout处理程序。但是,由于你的for循环是无限的,它永远不会达到这一步。

最简单的方法是使用async语法:

  const timer = ms => start => new Promise(res => setTimeout(res, ms));

  async function loop(){
    while(true){
      await timer(1000)();
      if(Math.random() > 0.9) return;
   }
 }

 timer(1000)()
    .then(loop)
    .then(timer(1000))
    .then(() => console.log("done"));

或者你可以使用递归异步函数:

async function loop(){
  await timer(1000)();
  if(Math.random() > 0.9)
     return true;
  else
     return loop();
}