Js阻塞機制,跟Js引擎的單線程處理方式有關,每一個window一個JS線程。所謂單線程,在某個特定的時刻只有特定的代碼可以被執行,並阻塞其它的代碼。html
因爲瀏覽器是事件驅動的(Event driven),所以瀏覽器中不少行爲是異步(Asynchronized)的,很容易有事件被同時或者連續觸發。當異步事件發生時,會建立事件並放入執 行隊列中,等待當前代碼執行完成以後再執行這些代碼,如鼠標點擊事件發生、定時器觸發事件發生、XMLHttpRequest完成回調這些事件,都會被放 入執行隊列中等待。html5
關於Js的阻塞機制,能夠看下面一段代碼,通常,咱們會認爲,這段代碼會log出來0,1,2瀏覽器
for(var i=0;i<3;i++){ setTimeout(function(){ console.log(i); }, (i+1)*1000);
}
而實際上,這段代碼log出來的結果是 3,3,3。這是js新手很容易遇到的問題,具體緣由就是由於for循環的阻塞機制。在上面的代碼中,setTimeout這個定時器須要等待for循環 執行完成,而for循環執行完成了以後,i已經爲3了,此時纔開始執行setTimeout,所以console.log(i)會是3。多線程
至於爲何i會是3,請回顧一下for循環的執行順序,當i爲2的時候,知足循環條件,執行代碼塊,而後i++,此時i爲3,不知足循環條件,不執行代碼塊,循環中止。異步
對於for循環,記住,是在不知足條件的狀況下中止循環,對於以上代碼,能夠看出,i=3的時候纔不知足。函數
其實,阻塞做爲js引擎的處理方式,咱們最好不要想着解決「阻塞」,而是讓咱們想執行的代碼,插入到「主線程」中。這麼說比較不易理解,仍是以上面的代碼爲例,直接上代碼好了spa
for(var i=0;i<3;i++){ (function(i){ setTimeout(function(){ console.log(i); }, (i+1)*1000); })(i) }
再上面的代碼中,咱們加了一個當即執行的匿名函數,而且將for循環的i做爲實參傳入進去。這樣,setTimeout就會被當即執行,而不會等待(這裏不太瞭解細節,就很少說了,大概猜想爲新開了一個臨時的線程,當即執行匿名函數,而後再當即切換回來)。線程
本文主要在說明如何解決這一類問題,對於底層原理,還待繼續挖掘。code
注意:html5支持Web worker功能,能夠寫多線程。htm