Javascript:如何使用setTimeout延迟确保使用多个嵌套循环的顺序执行?

时间:2014-02-08 15:36:22

标签: javascript settimeout

我一直在查看关于setTimeout()和循环延迟的许多SO帖子,但是还没有找到一个可行的解决方案。我正在浏览器中对一些数据进行动画演示,我需要多次重绘相同的序列,事件按特定顺序发生,包括带有延迟的内部循环。像这样:

for (var pass = 1; pass <= passes; pass++) {

    // 1. Prep some data, update DOM (must happen *before* inner loop)

    // 2. Run inner loop with delays (multiple DOM updates...)
    (function loopWithDelay() {
        setTimeout(function() {
            // Iterate on data
            // Update DOM on each iteration
            if ( !condition() ) { 
                loopWithDelay(); 
            }
        }, 250);   // delay at each iteration
    })(); 

    // 3. Do wrap-up calcs, update DOM (must happen *after* above loop)

}   // If more passes remain, repeat..

所以,我能够延迟内循环的迭代(第2部分),但是因为它是非阻塞的,所以第3部分立即执行,因此父循环不能正常工作。我有点理解Javascript的异步/非阻塞性质,但不能完全理解如何干净地完成这样的多序列(或实际上让它完全工作!)会喜欢这个特殊情况的一些建议。

3 个答案:

答案 0 :(得分:1)

如果您想使用异步方法,您的设计需要更改为event-driven而不是结构化。

基本上,您需要使用callback来处理延迟(如果您想要前沿,则需要使用Prom:D)

我在想这样的事:

(function() {
  var after_loop = function() {
    // Move 3 here
    // 3. Do wrap-up calcs, update DOM (must happen *after* above loop)
  }

  var loopWithDelay = function() {
    // update whatever DOM you want
    updateDom();

    // Check if we need to stop the looping
    if (stop_condition) {
      clearInterval(interval);
      after_loop();
    }
  }

  var interval = setInterval(loopWithDelay, 250);
})();

loopWithDelay将每250毫秒调用一次,当stop_condition为真时,它将停止运行并运行after_loop();

答案 1 :(得分:1)

这样做(我称之为回调循环):

function outerloop(pass, passes) {
    if (pass > passes) return;
    // 1. Prep some data, update DOM (must happen *before* inner loop)

    // 2. Run inner loop with delays (multiple DOM updates...)
    (function loopWithDelay() {
        setTimeout(function () {
            // Iterate on data
            // Update DOM on each iteration
            if (!condition()) {
                loopWithDelay();
            } else {
                outerloop(pass++, passes);
            }
        }, 250); // delay at each iteration
    })();

    // 3. Do wrap-up calcs, update DOM (must happen *after* above loop)

}
outerloop(1, passes);

答案 2 :(得分:0)

这样的事可能......?

var states = {
 beforeLoop: 0,
 innerLoop: 0,
 afterLoop: 0
};
var timeouts = {
 beforeLoop1: undefined,
 beforeLoop2: undefined,
 innerLoop1: undefined,
 innerLoop2: undefined,
 afterLoop1: undefined,
 afterLoop2: undefined
}
function setTimeoutType(fun,time,type){
 states[type]++;
 return setTimeout(fun,time);
}
function mainLoop(){
 if(beforeLoop1 == undefined)
  beforeLoop1 = setTimeoutType(beforeFun1,1000,'beforeLoop'); 
 if(beforeLoop2 == undefined)
  beforeLoop2 = setTimeoutType(beforeFun2,1000,'beforeLoop'); 
 if(states.beforeLoop == 0){
  if(innerLoop1 == undefined)
   innerLoop1 = setTimeoutType(innerFun1,1000,'innerLoop'); 
  if(innerLoop2 == undefined)
   innerLoop2 = setTimeoutType(innerFun2,1000,'innerLoop'); 
  if(states.innerLoop == 0){
   if(afterLoop1 == undefined)
    afterLoop1 = setTimeoutType(afterFun1,1000,'afterLoop'); 
   if(afterLoop2 == undefined)
    afterLoop2 = setTimeoutType(afterFun2,1000,'afterLoop'); 
   if(states.afterLoop == 0){
    // loops done
   }
   else setTimeout(mainLoop,1000);
  }
  else setTimeout(mainLoop,1000);
 }
 else setTimeout(mainLoop,1000);
}
function beforeFun1(){
 // code
 states.beforeLoop--;
}
function beforeFun2(){
 // code
 states.beforeLoop--;
}
function innerFun1(){
 // code
 states.innerLoop--;
}
function innerFun2(){
 // code
 states.innerLoop--;
}
function afterFun1(){
 // code
 states.afterLoop--;
}
function afterFun2(){
 // code
 states.afterLoop--;
}
function startThisHugeThing(){
 timeouts = {
  beforeLoop1: undefined,
  beforeLoop2: undefined,
  innerLoop1: undefined,
  innerLoop2: undefined,
  afterLoop1: undefined,
  afterLoop2: undefined
 }
 setTimeout(mainLoop,1000);
}