Event-Loop 詳解

JavaScript是單線程

JavaScript是單線程的,也就是說同一時間只能作一件事。 這和它運行在瀏覽器有關,做爲腳本語言,JavaScript只要用戶操做DOM以及用戶操做。 這決定了它只能是單線程,不然會帶來不少複雜的同步問題。瀏覽器

HTML5提出Web Worker標準,容許JavaScript腳本建立多個線程。
可是子線程徹底受主線程控制,且不得操做DOM。
因此,這個新標準並無改變JavaScript單線程的本質。
複製代碼

任務隊列

單線程意味着全部的任務都要排隊,前一個任務結束了纔會執行後一個任務。若是有些任務耗時過長,那麼就不得不一直等待下去。
在JavaScript中,耗時較長的操做主要是用戶操做、網絡請求、IO設備。每每這個時候CUP是處於閒置的,形成資源浪費。JavaScript設計者意識到網絡請求和IO設備等耗時操做能夠暫時無論他,先執行後面的任務,等耗時的操做有告終果回調再去以後再去執行相應操做。這樣大大的提升了資源的利用和代碼運行速度。
所以任務分爲同步任務和異步任務。簡單來講,同步任務是在主線程上的任務,該任務只有在前面任務執行完畢才能夠執行。異步任務則是進入任務隊列(task queue),當得知改任務能夠執行時纔會進入主線程執行。bash

同步異步執行順序以下:
(1)全部同步任務都在主線程上執行,造成一個執行棧

(2)主線程以外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。

(3)一旦"執行棧"中的全部同步任務執行完畢,系統就會讀取"任務隊列",看看裏面有哪些事件。那些對應的異步任務,因而結束等待狀態,進入執行棧,開始執行。

(4)主線程不斷重複上面的第三步。
複製代碼

事件和回調函數

任務隊列就是事件隊列。每當IO設備完成一項任務,就在任務隊列添加一個事件。意味着相關的異步操做能夠進入執行棧。
任務隊列中的事件,除了IO設備的事件之外,還包括一些用戶產生的事件(好比鼠標點擊、頁面滾動等等)。只要指定過回調函數,這些事件發生時就會進入"任務隊列",等待主線程讀取。
回調函數就是被主線程掛起的代碼,異步任務必須制定回調函數,當主線程開始執行異步操做,就是執行相應的回調函數。
任務隊列是先進先出的數據結構。同時主線程讀取任務隊列的規則是,主線程執行棧空是就去讀取任務隊列。網絡

Event Loop

下圖轉引自Philip Roberts的演講的PPT
有興趣的同窗看這裏《Help, I'm stuck in an event-loop》數據結構

相關文章
相關標籤/搜索