微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript – 在迭代到循环的下一次迭代之前完成FOR LOOP中的所有函数

我有一个像这样的功能

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 LOOP中的i = 0应该更改为i = 1,并且如果FOR循环内的所有条件都在当前迭代中完成了它们的工作.
目前这段代码的行为非常随机(因为我相信setTimeout).我怎样才能按照我的期望来完成这项工作?

我最近读过关于promises(对它们不太了解),但我不确定如何在这代码中实现它们,或者它们是否适用于这种情况……

解决方法:

最初的想法来自Nina Scholzanswer关于一些类似的问题.
如果你不喜欢promises和deferred对象,这个答案是好的. Othewise Kris Kowal的Q 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();

})();

代码说明

Iterator类有一个队列,它是数组和一些方法

一个

当你调用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); })();

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐