理解 Event Loop 2 - 來講真正的 Event Loop
前言
先以 Philip Roberts 著名的講解影片來鎮樓
瀏覽器可以分成三大塊
- JavaScript 引擎
stack
: 沒錯,就是前一篇講的 stackheap
: 變數、函數等等存放的記憶體空間
- Web API
- 其實這些東西都不包含在 JS 引擎裡面,而是瀏覽器內部的 API,例如:
onClick
事件ajax
: 發出非同步請求setTimeOut
: 計時器
callback queue
( 或稱event queue
)
範例 1
console.log("Hi!");
setTimeout(function timeout() {
console.log("Time is out");
}, 5000);
console.log("This is second one");
請搭配 視覺化 服用
執行順序
- 整體程式碼
main
放入 call stack,開始執行程式 - 程式碼碰到
console.log("Hi!")
放進 call stack,執行並 pop off - 程式碼碰到
setTimeout
- oh 這個是一個非同步 Web API,這就是重點了
- 先移交給 Web API 開始計時 ( 此時還不會執行裡面的 callback function )
- 程式碼碰到
console.log("This is second one")
放進 call stack,執行並 pop off - 5 秒到了,把
setTimeout
裡面的 callback 放到 queue 裡面待命 - 整體程式碼執行完畢,
main
pop off - 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 的執行過程
- 一般的程式,call stack 如往常般運行執行程式碼,
- 碰到非同步的部分,例如
setTimeOut
、ajax
則移交給 web api 進行處理 setTimeOut
、ajax
處理完畢後,把後續的 callback 放進 event queue- 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 task
跟 micro task
了,這兩個不同性質,會影響非同步的優先順序,下回分曉