淺析 JS 中的 EventLoop 事件循環(新手向)

Event Loop 這個概念相信大家或多或少都瞭解過,但是有一次被一個小夥伴問到它具體的原理的時候,感覺自己只知道個大概印象,於是計劃着寫一篇文章,用輸出倒逼輸入,讓自己重新學習這個概念,同時也能幫助更多的人理解它~

概念

JavaScript 是一門 單線程 語言,即同一時間只能執行一個任務,即代碼執行是同步並且阻塞的。

eg. 這就像只有一個窗口的銀行,客戶需要一個一個排隊辦理業務。

只能同步執行肯定是有問題的,所以 JS 有了一個用來實現異步的函數:setTimeout

下面要講的 Event Loop 就是爲了確保 異步代碼 可以在 同步代碼 執行後繼續執行的。

由於涉及到的相關概念較多,我們先從最簡單的來。

隊列(Queue)

隊列 是一種 FIFO(First In, First Out) 的數據結構,它的特點就是 先進先出

eg. 生活中最常見的例子就是排隊啦,排在隊伍最前面的人最先被提供服務。

棧(Stack)

是一種 LIFO(Last In, First Out)的數據結構,特點即 後進先出

eg. 大家都吃過桶裝薯片吧~薯片在包裝的時候只能從頂部放入,而吃的時候也只能從頂部拿出,這就叫後進先出哈

調用棧(Call Stack)

棧我們已經知道了,那麼什麼是 調用棧 呢 ?

它本質上當然還是個棧啦 廢話,關鍵在於它裏面裝的東西,是一個個待執行的函數。

Event Loop 會一直檢查 Call Stack 中是否有函數需要執行,如果有,就從棧頂依次執行。同時,如果執行的過程中發現其他函數,繼續入棧然後執行。

先拿兩個函數來說:

  • 棧空
  • 現在執行到一個 函數A,函數A 入棧
  • 函數A 又調用了 函數B,函數B 入棧
  • 函數B 執行完後 出棧
  • 然後繼續執行 函數A,執行完後A也 出棧
  • 棧空

更復雜一點的話,來看一段代碼:

call-stack-code.png

這段代碼在 調用棧中的運行順序如下圖:

call-stack-process.png

這個調用棧其實大家經常會見到,就是在控制檯報錯的時候,錯誤信息顯示的就是當前時刻調用棧的狀態。

But, 上面我們討論的其實都是同步代碼,代碼在運行的時候只用 調用棧 解釋就可以了。

那麼,假如我們發起了一個網絡請求(request),或者設置了一個定時器延時(setTimeout),一段時間後的代碼(回調函數)肯定不是直接被加到調用棧吧?

這時就要引出 事件表格(Event Table)事件隊列 (Event Queue)

Event Table

Event Table 可以理解成一張 事件->回調函數 對應表

它就是用來存儲 JavaScript 中的異步事件 (request, setTimeout, IO等) 及其對應的回調函數的列表

Event Queue

Event Queue 簡單理解就是 回調函數 隊列,所以它也叫 Callback Queue

當 Event Table 中的事件被觸發,事件對應的 回調函數 就會被 push 進這個 Event Queue,然後等待被執行

Event Loop

先來看一個流程圖:

event-loop-process.png

  • 開始,任務先進入 Call Stack
  • 同步任務直接在棧中等待被執行,異步任務從 Call Stack 移入到 Event Table 註冊
  • 當對應的事件觸發(或延遲到指定時間),Event Table 會將事件回調函數移入 Event Queue 等待
  • 當 Call Stack 中沒有任務,就從 Event Queue 中拿出一個任務放入 Call Stack

Event Loop 指的就是這一整個圈圈:

它不停檢查 Call Stack 中是否有任務(也叫棧幀)需要執行,如果沒有,就檢查 Event Queue,從中彈出一個任務,放入 Call Stack 中,如此往復循環。

好啦,不知道有沒有看明白呢?放一張更經典的圖:

event-loop.png

其中與 Event Queue 對應的還有一個叫 Job Queue,它主要是用來執行 Promise 的,這兩種 Queue 有什麼區別呢?

這就涉及到 宏任務 (macro task) 和 微任務 (micro task) 了,我們放在下篇再講~

參考文章

原文鏈接
MDN EventLoop
javascript-event-loop
understanding-js-the-event-loop
這一次,徹底弄懂JavaScript執行機制
understanding-event-loop-call-stack-event-job-queue-in-javascript

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章