简体   繁体   English

如何成功地在承诺链中间循环

[英]How to successfully loop in the middle of a promise chain

I'm putting together a promise chain, new to this so apologies. 我正在整理一个许诺链,这很抱歉。 What I want to do is, for any errors in any particular function, I want to wait a second and try again until it succeeds, then continue with the promise chain as per the original plan. 我想要做的是,对于任何特定功能中的任何错误,我都希望稍等片刻,然后重试直到成功为止,然后按照原始计划继续执行Promise链。

I tried an if statement that called the function again if there was an error message and resolved if there was not, but this would not continue with the promise chain on a success. 我尝试了一条if语句,如果有错误消息,则再次调用该函数,如果没有,则解决,但是如果成功,则不会继续诺言链。

I then worked a solution that included a for loop built into the function, as below: 然后,我工作了一个解决方案,其中包括一个内置于函数中的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);

It completes firstMethod and then hangs when I try to run it. 它先完成firstMethod,然后在我尝试运行它时挂起。 If I comment out the setTimeout in the secondMethod it works, but I feel this is not emulating the real case scenario I want to use this for. 如果我在secondMethod中注释掉setTimeout,它可以工作,但是我感觉这不是在模拟我要使用的实际情况。

Where am I going wrong? 我要去哪里错了? Is there a better way to loop mid promise chain until you achieve a particular result, then continue with the promise chain? 有没有更好的方法来循环中途承诺链,直到获得特定结果,然后继续进行承诺链?

You can replace the secondMethod with 您可以将secondMethod替换为

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

The reason your code doesn't work, because the condition to stop for loop is in asynchronous, so it will be deferred, so the for loop will go forever. 您的代码无法正常工作的原因,因为停止for循环的条件是异步的,因此它将被推迟,因此for循环将永远持续下去。

Update Without using IIFE 不使用IIFE进行 更新

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 {
                    console.log('the number wasn\'t big enough', randomNumber);
                    doItUntilGetEnoughBigNumber();
                }
            }, 1000)
        }
        doItUntilGetEnoughBigNumber();
    });
    return promise;
};

The important thing about async events (eg when setTimeout finishes) is that the handler is not called directly, but the event is put into the so called event queue. 关于异步事件(例如,setTimeout完成时)的重要事情是,不直接调用处理程序,而是将事件放入所谓的事件队列中。 The javascript engine (the event loop) takes one event after another out of it and executes it, when its done it takes the next one. javascript引擎(事件循环)从一个事件中接出另一个事件并执行该事件,完成后则接下一个事件。 At first it will execute your for loop and set all the timeouts. 首先,它将执行for循环并设置所有超时。 Then when its done and one second passed it will start executing the setTimeout handlers. 然后,当完成并经过一秒钟时,它将开始执行setTimeout处理程序。 But as your for loop is infinite, it will never reach this step. 但是,因为您的for循环是无限的,所以它永远不会到达这一步。


The easiest would be to use the async syntax: 最简单的方法是使用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"));

Alternatively you could use a recursive async function: 或者,您可以使用递归异步函数:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM