2013-05-15 78 views
2

这是一个后续问题:How to suspend JavaScript to allow render的Javascript嵌套循环使用的setTimeout

我写了,做了那种暂停循环功能(允许与渲染):

function loop(count, callback){ 
    var counter = 0 
    var iteration = function(){ 
     callback(counter) 
     counter ++; 
     if (counter < count){ 
      setTimeout(iteration, 0) 
     } 
    } 
    iteration(); 
} 

这很好用,例如loop(100, function(i){ console.log(i) })。并允许浏览器在每次迭代之间进行渲染。

但是,在循环之后执行填充时发生问题,因为不能保证循环已完成。其实,我认为它有一个保证,它有而不是(因为主线程在setTimeout第一次被调用后继续)。这是这些嵌套循环样时加剧:

loop(10, function(i){ 
    loop(10, function(j){ 
     console.log(i + '-' + j) 
    }) 
}) 
/// This definitely does not output the numbers in order... 

我的使用情况是,我运行了一些仿真的,每个都包括多个步骤,我想呈现在每个之间。我是否以这种错误的方式去做?

+0

你可以看看[这个答案](http://stackoverflow.com/questions/15963590/how-to-synch- javascript-callbacks/15964626#15964626),其中还讨论了同步异步代码。 –

+0

如果你想在循环之后执行某些事情,可以使用类似'function loop(count,callback,callback_finish){if(counter Passerby

+0

_“,我想在每个之间渲染”_为什么需要超时0? – Simon

回答

2

这是我会怎么做:阅读下面的OP的评论后更新的答案:

编辑

function loop(count, callback, done) { 
    var counter = 0; 
    var next = function() { 
     setTimeout(iteration, 0); 
    }; 
    var iteration = function() { 
     if (counter < count) { 
      callback(counter, next); 
     } else { 
      done && done(); 
     } 
     counter++; 
    } 
    iteration(); 
} 

loop(100, function (i, next) { 
    console.log(i); 
    next(); 
}) 


loop(10, function (i, nextI) { 
    loop(10, function (j, nextJ) { 
     console.log(i + '-' + j); 
     nextJ(); 
    }, nextI); 
}); 

输出:

1 
1-1 
2 
1-2 
3 
1-3 
4 
1-4 
5 
1-5 
6 
1-6 
7 
1-7 
8 
1-8 
9 
1-9 
10 
11 
2-1 
<<...>> 
97 
98 
99 

http://jsfiddle.net/4Rw2H/1/

loop功能有第三个参数done将在循环完成后运行(如果存在)。回调将有第二个参数next,当您想要运行下一次迭代时需要调用该参数。

这样,你可以在循环内部调用一个异步函数,并且仍然让它按顺序运行。

+0

看起来不错,虽然它很难掌握。但是如果我直接复制这个,我会在'loop'里面失去'暂停'功能,不是吗?循环函数的目标是制作一个暂停循环单线程。 – noio

+0

@Noio,对不起,我不明白'暂停'功能是什么意思?我认为功能可能与您在问题中发布的代码完全相同。 – Dogbert

+0

我的原始循环函数的目的是用'setTimeout(0)'调用每个下一个迭代,以允许浏览器呈现DOM。所以你的功能是相同的,可能只有当我调用'setTimeout(nextJ,0)'? – noio

0

这似乎正常工作:

JSFIDDLE

var log = function (i) { console.log(i) }, 
    loop = function (count, callback) { 
     callback(count); 
     count--; 
     count > 0 && arguments.callee(count, callback); 
    } 

loop(10, log); 
console.log('end'); 
loop(5, log);