Event Loop 學習筆記

xiaopi發表於2018-03-27

JavaScript 的執行緒

作為瀏覽器語言,JavaScript 會對 DOM 進行操作,如果存在多個執行緒同時操作 DOM,一個執行緒建立了一個節點,另外一個執行緒去刪除這個節點,瀏覽器渲染就會亂套。所以,JavaScript 被設計成單執行緒。

單執行緒指的是 JavaScript 引擎解析和執行程式碼的執行緒只有一個,這個執行緒為主執行緒,所有的同步任務都在主執行緒上執行。

同步和非同步

單執行緒就意味著所有的任務都是同步的,下一個任務必須在上一個任務完成後再執行。假如有一個同步的網路請求,我們等待的時間是不確定的,在請求響應前,瀏覽器就會處於阻塞狀態。

所以 JavaScript 提供了非同步任務,我們不需要關心非同步任務何時響應,這樣就可以保證主執行緒的任務暢通無阻的執行下去。

任務佇列

非同步任務不進入主執行緒,而是進入任務佇列,當非同步任務完成,任務佇列通知主執行緒,該任務才會進入主執行緒。佇列的特點是先進先出,任務佇列中的事件會之按照放入的時間先後順序執行。

Event Loop

由於主執行緒讀取任務佇列的的過程是迴圈不斷的,所以這種機制被稱為 Event Loop(事件迴圈)。

Event Loop 學習筆記

  • 所有同步任務都在主執行緒(stack)上執行,形成一個執行棧。
  • 主執行緒之外,還存在一個任務佇列(callback queue),只要非同步任務有了執行結果,就在任務佇列之中放置一個事件。
  • 一旦執行棧中的所有同步任務執行完畢,系統就會讀取任務佇列,將佇列中的事件放到執行棧中依次執行。
  • 主執行緒從任務佇列中讀取事件,這個過程是迴圈不斷的。

巨集任務和微任務

任務佇列可分為巨集任務佇列和微任務佇列

  • 巨集任務:setTimeout、setInterval、setImmediate、I/O 等。
  • 微任務:then、process.nextTick、Object.observer 等。

在瀏覽器環境中,當執行棧的任務執行完畢,先去讀取微任務佇列,微任務執行完畢,巨集任務佇列讀取一個事件放到執行棧去執行,執行完畢後再去取微任務佇列,如此重複。

在 Node 環境中,Event Loop 分為 6 個階段,每一個階段對應著一個巨集任務佇列。

Event Loop 學習筆記

與瀏覽器環境不同,Node 環境下,當執行棧的任務執行完畢後,清空微任務佇列。取到巨集任務佇列所有事件去執行,執行完畢轉到下一個階段,此時去清空微任務佇列。

相關文章