Skip to main content

理解 Event Loop 2 - 來講真正的 Event Loop

前言

先以 Philip Roberts 著名的講解影片來鎮樓

瀏覽器可以分成三大塊

  1. JavaScript 引擎
    • stack : 沒錯,就是前一篇講的 stack
    • heap : 變數、函數等等存放的記憶體空間
  2. Web API
    • 其實這些東西都不包含在 JS 引擎裡面,而是瀏覽器內部的 API,例如:
    • onClick 事件
    • ajax : 發出非同步請求
    • setTimeOut : 計時器
  3. callback queue ( 或稱 event queue )

範例 1

console.log("Hi!");

setTimeout(function timeout() {
console.log("Time is out");
}, 5000);

console.log("This is second one");

請搭配 視覺化 服用

執行順序

  1. 整體程式碼 main 放入 call stack,開始執行程式
  2. 程式碼碰到 console.log("Hi!") 放進 call stack,執行並 pop off
  3. 程式碼碰到 setTimeout
    • oh 這個是一個非同步 Web API,這就是重點了
    • 先移交給 Web API 開始計時 ( 此時還不會執行裡面的 callback function )
  4. 程式碼碰到 console.log("This is second one") 放進 call stack,執行並 pop off
  5. 5 秒到了,把 setTimeout 裡面的 callback 放到 queue 裡面待命
  6. 整體程式碼執行完畢,main pop off
  7. stack 全都清空了,好的,可以把 queue 裡面的任務放進去 stack 繼續執行了,執行 console.log("Time is out")

範例 2: 真正理解 Event Loop

console.log("Hi!");

setTimeout(function timeout() {
console.log("Time is out");
}, 0);

console.log("This is second one");

如果將 setTimeout 改為計時 0 秒會發生什麼事? 執行順序還是一樣 "Hi"、"This is second one"、"Time is out",不會因為 0 秒就讓 setTimeout 內的 callback 變成立即執行

來總結一下 event loop 的執行過程

  1. 一般的程式,call stack 如往常般運行執行程式碼,
  2. 碰到非同步的部分,例如 setTimeOutajax 則移交給 web api 進行處理
  3. setTimeOutajax 處理完畢後,把後續的 callback 放進 event queue
  4. event Loop 會不斷不斷檢查 stack,若 stack 已經空了,就把 queue 的東西抓過來放到 stack

要注意的是,Event Queue 中的 「Queue」,也是一種資料結構,和 Stack 不一樣,是採先進先出 ( FIFO ) ,最先進來的就先執行

我們可以繼續在 這裡 知道,若有兩個 setTimeOut,到了 event queue 的時候,最先進來會最先執行,其實就是依照

小結

白話來說,event loop 會先讓 stack 優先處理 同步 的程式碼,非同步 則轉移瀏覽器 web api 處理,等到 同步 的部分都已完成 ( stack 被清空 ),再來繼續收尾 非同步 的程序

以實際運作機制來看,event loop 是一個司令,不斷檢查 call stack 是不是空的,若已被清空,再來開始 event queue 的東西塞到 stack

但是如果再把 Promise 考慮進去,非同步的部分又可以區分 macro taskmicro task 了,這兩個不同性質,會影響非同步的優先順序,下回分曉

Reference

所以說 event loop 到底是什麼玩意兒?| Philip Roberts | JSConf EU