2015-10-13 29 views
2

我細讀了一套在線的JavaScript的面試問題,發現以下問題:理解的setTimeout爲了

function printing() { 
    console.log(1); 
    setTimeout(function() { console.log(2); }, 1); 
    setTimeout(function() { console.log(3); }, 2); 
    setTimeout(function() { console.log(4); }, 0); 
    console.log(5); 
} 
printing(); 

我期待下面的代碼以下內容打印到控制檯:1,5,4,3 ,2 我的理由是console.log(1)和console.log(2)首先被執行,而setTimeout被髮送到eventloop,並等待所有事情先完成。一旦打印出5,JS就會查看隊列,並且4,3,2會在下一個按下/彈出。

但是,在我的Chrome瀏覽器中,我注意到1,5,2,4,3代替。

我很困惑,但同時有一個預感,它可能是由於超時延遲的小增量導致打嗝(也許是瀏覽器的事?)。我之所以這樣做,是因爲我爲每個數字添加了兩個零以便延遲變爲100,200和0。

任何人都可以澄清引擎蓋下發生了什麼,以及任何我應該瞭解延遲的細節?

+1

很確定超時的最小有效值是1,所以0移到1,因此發生在之後。不確定。無論如何,我不會使用小於16ms的定時器(60Hz),因爲這是Windows的默認定時器分辨率,我不想僅僅爲了使用高分辨率定時器。 –

+0

我注意到下面的鏈接,其中最小值爲4ms和10ms取決於瀏覽器:http://stackoverflow.com/questions/9647215/what-is-minimum-millisecond-value-of-settimeout – bigbitecode

+0

這可能是值得注意的是,在[w3 spec](http://www.w3.org/TR/html5/webappapis.html)第6.4節規定'... timeout小於4,然後增加超時到4'(如果你的ms值是根據規範0-3它將被設置爲4),並且與此同時,您可能會發現以下有關Javascript計時的有用信息[Javascript Javascript定時器如何工作](http://ejohn.org/blog/how-javascript-timers-工作/) –

回答

3

這裏我給你的執行如何去一個例子:

console.log(1);         // Run log "1" 
    setTimeout(function() { console.log(2); }, 1); // Add to queue timer1 
    setTimeout(function() { console.log(3); }, 2); // Add to queue timer2 
    setTimeout(function() { console.log(4); }, 0); // Add to queue timer3 
    console.log(5);         // Run log "5" 
    // In queue [timer1, timer2, timer3] 

    // [tick timer 1 => 0 time left => execute] log "2" 
    // [tick timer 2 => 1 time left] 
    // [timer 3 => 0 time left => execute] log "4" 
    // [tick timer 2 => 0 time left => execute] log "3" 

功能setTimeout(... , 0)setTimeout(..., 1)將同樣的方式工作。當我們在「超時隊列」中勾選每個定時器時,我們也檢查是否還有剩餘時間。所以setTimeout(..., 1)將會打勾並執行,而setTimeout(... , 0)將會執行。

+0

啊,這很有道理。由於JS是同步的,它將按照定時器隊列的順序執行,並首先使timer1到期,使其執行。真正有用的評論,謝謝! – bigbitecode

+0

每個瀏覽器/引擎都一樣嗎?我的firefox日誌'1 5 4 2 3' – Anonymous0day

+0

@ Anonymous0day不,不是。不同的瀏覽器可以以不同的方式處理定時器。我上面解釋的是它在OP瀏覽器中發生的情況(我認爲它會是chrome)。它看起來像Firefox會以不同的方式在隊列中的每個計時器上進行打勾(它可能會以最小的時間先打勾,但這是一個猜測)。 –

0

您必須瞭解調用堆棧。所有函數調用都放置在調用堆棧上,如果堆棧爲空,則調用該函數。如果堆棧有條目,那麼直到堆棧上的當前調用完成纔會調用該函數。

當超時時,超時將調用置於調用堆棧上。他們異步執行此操作。因此可以在當前執行期間將調用放置在調用堆棧上。

超時未優先,堆棧中的第一個執行。 1毫秒超時將跳過調用堆棧的0毫秒,因此首先執行。