2013-05-15 76 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);