在迭代到循环的下一个迭代之前,完成FOR LOOP中的所有函数 [英] Complete all functions inside a FOR LOOP before iterating to next iteration of the loop

查看:200
本文介绍了在迭代到循环的下一个迭代之前,完成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);

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

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








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


$ / code $ / pre


现在我想要从这个函数开始,当所有的条件都完成了他们预期的任务之后,才会移动到FOR循环的下一个迭代。换句话说,FOR LOOP中的 i = 0 应该变成 i = 1 ,如果所有的FOR循环中的条件已经在当前迭代中完成了他们的工作。


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



我最近读了承诺(不太了解他们),但我不知道如何实现他们在这个代码或者如果他们将在这种情况下工作...

解决方案

最初的想法来自 Nina Scholz 对一些类似的问题。
如果你不喜欢承诺和延期对象,这个答案是好的。无论如何 Q库将是更好的选择。 data-console =truedata-babel =false> div class =snippet-code snippet-currently-hidden>

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();(函数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('计数器值是'+计数器);},100); iterator.add(fillNextIteration,100); iterator.next();})();


$ b

代码解释

Iterator类有一个队列,它和数组以及一些方法:

$ b next



如果队列中有任何回调,它将首先获取并执行。当您调用 Array#shift 时,它将删除并返回数组中的第一项。当这个项目是一个函数,那么你可以通过在它前面添加括号来调用它。这里是扩展版本:

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

等待



这个方法会给队列增加一个额外的回调函数,超时后调用下一个方法。这个是为了创建预期的延迟。

$ add
这个方法调用等待所需的延迟,然后把另一个函数附加到队列中这将调用回调,然后调用下一步使回调链运行。

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

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





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



self调用函数
正如你可以看到 fillNextIteration 是自调用的。
这有助于减少一个调用,并像这样工作:

  function f(){}; 
f();

最后要提的是
您可以创建一个循环在自己内部调用一个函数。如果没有延迟或停止撤销,那么这将是一个僵局。所以这是另外一个循环:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $($)


Say i have a function like :

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


Now what i want from this function is that when all of the conditions have performed their intended task, only then it should move to the next iteration of FOR loop. In other words, i=0 in FOR LOOP should change to i=1 and so-on iff all of the conditions inside the FOR loop have completed their job in current iteration.

Currently behaviour of this code is very random (because of setTimeout i believe). How can i make this work as per my expectations?

I recently read about promises (don't know much about them) but i'm not sure how to implement them in this code or if they will work in this case...

解决方案

The original idea came from the answer of Nina Scholz on some similar question. this answer is good if you don't like promises and deferred object. Othewise Kris Kowal's Q library would be a better choice.

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();

})();

Code Explanation

Iterator class has one queue which is and array and some methods:

next

when you call next() if there is any callback in queue it will fetch first and execute that. when you call Array#shift it removes and returns first item from array. When this item is a function then you can invoke it by adding parentheses in front of it. here is the expanded version:

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

wait

This method will add an extra callback to queue which after a timeout calls the next method. this one is for creating the expected delay.

add This method calls the wait with desired delay then attaches another function to queue which will call the callback and then calls next to make callback chain running.


fillNextIteration after explaining the iterator there is another loop here on function fillNextIteration this starts with the conditions for the first iteration for example:

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

you can check all conditions and then if required add the callback as shown. after all condition finished add fillNextIteration as last action to continue the loop.

self invoking function As you can see fillNextIteration is self invoked. This helps to reduce one invoke and works like this:

function f(){};
f();

Last thing to mention you can create a loop by calling a function inside itself. if there is no delay or stop for revoke then it would be a deadlock. So this is another loop as well:

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

这篇关于在迭代到循环的下一个迭代之前,完成FOR LOOP中的所有函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆