【问题标题】:Complete all functions inside a FOR LOOP before iterating to next iteration of the loop在迭代到循环的下一次迭代之前完成 FOR LOOP 中的所有函数
【发布时间】:2016-11-04 16:09:17
【问题描述】:

假设我有一个类似的功能:

var bigArray = [1,2,3,4,5.........n];
for(var i=0; i<bigArray.length; i++){
  if(someCondition){
     setTimeout(function(){
       ..do_stuff..
       callSomeFunction();
     }, someDelayTime);
  }

  if(someCondition){
     setTimeout(function(){
       ..do_stuff..
       callSomeFunction();
     }, someDelayTime);
  }

  if(someCondition){
     setTimeout(function(){
       ..do_stuff..
       callSomeFunction();
     }, someDelayTime);
  }
  .
  .
  .
  .
  .
  .
  .
  .
  if(someCondition){
     setTimeout(function(){
       ..do_stuff..
       callSomeFunction();
     }, someDelayTime);
  }
}


现在我想要从这个函数中得到的是,当所有条件都执行了它们的预期任务时,它才应该移动到 FOR 循环的下一次迭代。换句话说,FOR 循环中的i=0 应该更改为i=1 等等,如果 FOR 循环内的所有条件在当前迭代中都完成了它们的工作。

目前这段代码的行为是非常随机的(因为我相信setTimeout)。我怎样才能按照我的期望进行这项工作?

我最近阅读了有关 promises 的内容(对它们了解不多),但我不确定如何在这段代码中实现它们,或者它们是否能在这种情况下工作......

【问题讨论】:

  • 您不能将同步循环与这样的异步行为混合在一起。您可能想要做的是将 promise 映射到数组并对其进行排序。
  • 对不起,但由于我对承诺的了解很少,我无法解释您建议的解决方案。不过感谢您的快速回复!
  • @TusharShukla 我认为也可以对原创想法进行投票。
  • @mortezaT 我相信你说的是接受的答案。好吧,我真的很感谢大家的帮助,我很感谢他们,但是我仍然没有按照我的代码要求解决这个问题。当然,一旦我找出解决方案,我会接受答案。
  • @TusharShukla 那有什么问题?

标签: javascript jquery for-loop settimeout es6-promise


【解决方案1】:

希望这将通过承诺 chaning 起作用

callSomeFunction1().then(function() {
   callSomeFunction2();
}).then(function() {
   callSomeFunction3();
})

【讨论】:

    【解决方案2】:

    最初的想法来自Nina Scholzanswer 在一些类似的问题上。 如果您不喜欢承诺和延迟对象,这个答案很好。否则 Kris KowalQ library 会是更好的选择。

    function Iterator() {
      var iterator = this;
      this.queue = [];
    
      this.add = function(callback, wait) {
        iterator.queue.push(iterator.wait(wait));
    
        iterator.queue.push(function() {
          callback();
          iterator.next();
        });
      };
    
      this.wait = function(wait) {
        return function() {
          setTimeout(iterator.next, wait);
        };
      };
    
      this.next = function() {
        iterator.queue.length && iterator.queue.shift()();
      };
    }
    
    var arr = [1, 2, 3, 4, 5],
      counter = -1;
    
    var iterator = new Iterator();
    
    (function fillNextIteration() {
      if (counter >= arr.length)
        return;
      counter++;
      iterator.add(function() {
        console.log('1 - counter value is ' + counter);
      }, 100);
      iterator.add(function() {
        console.log('2 - counter value is ' + counter);
      }, 100);
      iterator.add(function() {
        console.log('3 - counter value is ' + counter);
      }, 100);
      iterator.add(function() {
        console.log('4 - counter value is ' + counter);
      }, 100);
    
      iterator.add(fillNextIteration, 100);
      iterator.next();
    
    })();

    代码说明

    迭代器类有一个队列,它是数组和一些方法:

    下一个

    当您调用next() 时,如果队列中有任何回调,它将首先获取并执行该回调。当您调用 Array#shift 时,它会从数组中删除并返回第一项。当此项为函数时,您可以通过在其前面添加括号来调用它。这是扩展版:

    if (iterator.queue.length > 0) {
        var callback = iterator.queue.shift();
        callback();
    }
    

    等待

    此方法将向队列添加一个额外的回调,该回调在超时后调用下一个方法。这个是为了产生预期的延迟。

    添加 此方法以所需的延迟调用等待,然后将另一个函数附加到队列中,该函数将调用回调,然后调用 next 以使回调链运行。


    fillNextIteration 在解释了迭代器之后,函数fillNextIteration 上还有另一个循环,这从第一次迭代的条件开始,例如:

    if (someConditionIsTrue) {
        iterator.add(function() {
            doWhatShallBeDone;
        }, delay);
    }
    

    您可以检查所有条件,然后根据需要添加回调,如图所示。 在所有条件完成后添加 fillNextIteration 作为最后一个操作以继续循环。

    自调用函数 如您所见,fillNextIteration 是自调用的。 这有助于减少一次调用,其工作方式如下:

    function f(){};
    f();
    

    最后一件事 您可以通过调用自身内部的函数来创建循环。如果没有延迟或停止撤销,那么这将是一个僵局。所以这也是另一个循环:

    (function loop() { setTimeout(loop, delay); })();
    

    【讨论】:

    • 你能解释一下这段代码吗,我不太熟悉这种风格的js代码。 (我的意思不是冒犯)。
    • @TusharShukla 添加了一些注释。希望有帮助
    • 感谢您的解释,现在我可以将其用于我想要的目的。非常感谢!
    【解决方案3】:

    请试试这个:

    bigArray = [1, 2, 3, 4, 5.........n];
    neededStuff = 10; // Number of finished works you need below
    stuffOK = neededStuff;
    function mainFunction(i) {
    
        function loopFunction(i) {
            if (someCondition) {
                setTimeout(function () {
                    // .. do_stuff..
                    stuffOK++;
                    callSomeFunction();
                }, someDelayTime);
            }
    
            if (someCondition) {
                setTimeout(function () {
                    // .. do_stuff..
                    stuffOK++;
                    callSomeFunction();
                }, someDelayTime);
            }
    
            if (someCondition) {
                setTimeout(function () {
                    // .. do_stuff..
                    stuffOK++;
                    callSomeFunction();
                }, someDelayTime);
            }
            /*
    
             ...
    
             */
    
            if(someCondition) {
                setTimeout(function () {
                    // .. do_stuff..
                    stuffOK++;
                    callSomeFunction();
                }, someDelayTime);
            }
        }
    
        if (stuffOK == neededStuff) {
            i++;
            stuffOK = 0; // reinit counter
            loopFunction(i);
        }
    
        setTimeout('mainFunction(' + i + ');', 100);
    
    }
    mainFunction(-1);
    

    【讨论】:

      猜你喜欢
      • 2014-07-30
      • 1970-01-01
      • 1970-01-01
      • 2020-07-02
      • 2020-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-14
      相关资源
      最近更新 更多