天天看點

事件隊列

js任務隊列

有js的單線程的特質決定那js為什麼是單線程呢?

本段來自阮老師的部落格中對JS單線程的介紹。JavaScript語言的一大特點就是單線程,也就是說同一時間隻能做一件事,那麼為什麼JavaScript不能有多個線程呢,還能提高效率?JavaScript的單線程與他的用途有關,作為浏覽器的腳本語言,JavaScript的主要用途是和使用者互動,以及操作DOM,這就決定了他隻能是單線程,否則會帶來很複雜的同步問題。比如假如JavaScript同時有兩個線程,一個線程在某個節點上添加内容,另個線程删除了這個節點,那麼浏覽器應該以哪個線程為準?是以為了避免複雜性,從一誕生,JavaScript就是單線程,這已經成了這門語言的核心特征,将來也不會改變為了利用多核CPU的計算能力,HTML5提出Web Worker标準,允許JavaScript腳本建立多個線程,但子線程完全受主線程控制,且不得操作DOM,是以這個新标準并沒有改變JavaScript單線程的本質任務隊列的本質:

◇ 所有的同步任務都在主線程上進行,形成一個執行棧

◇ 主線程外還存在一個任務隊列,隻要異步任務有了結果,就在任務隊列之中放置一個事件

◇ 一旦執行棧中的所有同步任務執行完畢,系統就會讀取任務隊列,看看裡面有哪些事件。哪些對應的異步任務結束等待狀态,進入執行棧,開始執行。

◇ 主線程不斷重複上面的第三步

會進入事件隊列的事件setTimeout(),ajax的回調函數,事件處理函數(綁定的事件函數)。。。。普通的函數不會進入事件隊列

關于 setTimeOut、setImmediate、process.nextTick()的比較

setTimeout()将事件插入到了事件隊列,必須等到目前代碼(執行棧)執行完,主線程才會去執行它指定的回調函數。當主線程時間執行過長,無法保證回調會在事件指定的時間執行。浏覽器端每次setTimeout會有4ms的延遲,當連續執行多個setTimeout,有可能會阻塞程序,造成性能問題

setImmediate()事件插入到事件隊列尾部,主線程和事件隊列的函數執行完成之後立即執行。和setTimeout(fn,0)的效果差不多。服務端node提供的方法。浏覽器端最新的api也有類似實作:window.setImmediate,但支援的浏覽器很少。

process.nextTick()插入到事件隊列尾部,但在下次事件隊列之前會執行。也就是說,它指定的任務總是發生在所有異步任務之前,目前主線程的末尾。大緻流程:目前”執行棧”的尾部–>下一次Event Loop(主線程讀取”任務隊列”)之前–>觸發process指定的回調函數。伺服器端node提供的辦法。用此方法可以用于處于異步延遲的問題。可以了解為:此次不行,預約下次優先執行。

關于消除 setTimeout 延遲的實踐:soon.js// See http://www.bluejava.com/4NS/Speed-up-your-Websites-with-a-Faster-setTimeout-using-soon//

繼續閱讀