先講結論: Event Loop 就是一個永不停歇的調配 callback 事件佇列(Callback Queue)與目前該執行哪個程式(Call Stack)的橋樑
那我們開始囉~
🍘 先來聊聊,先備知識
JS 引擎是單一執行緒(thread)的程式語言,不可單獨運作,需在一個宿主環境中(hosting envirement)才能運行,像是典型的 web 瀏覽器、NodeJs,到各種內嵌裝置。
不論在哪個環境中,皆有一個共通的主軸 (thread),當每次 JS 被調用時,用來處理程式的多個組塊分布在各個時間的執行工作(?),特性為永遠都排程了事件,這個機制就叫 Event Loop。換句話說,JS 引擎本身是沒有時間概念的。
好的,上述是根據小黃書( You don’t know Js )的定義,可能是翻譯的關係,有一句話實在很饒口,完全不知道在說什麼XD
沒關係,作為講求實務的工程師,讓我們直接以範例來理解~
以下為 Web 瀏覽器 – V8 為例
JS 引擎:
- Memory heap (The heap) : 底層記憶體,用來配置物件與變數
- Call Stack: 持續追蹤目前程式碼跑到哪裡,每執行一個 function,便疊加上去,function 執行完,便從疊加中移除,再執行下一個 function。為單一執行緒的後進先出 Stack 結構
瀏覽器環境:
- Web API: 瀏覽器環境所提 供的各種 API 接口,允許與 JS 做更多的互動,像是常用的 Dom, AJAX, setTimeout。
「竟然都不存在於 JS 引擎中,在研究的過程中,這點也令我滿驚訝的XD」 - Callback Queue: 紀錄來自於 Web API callback 事件的觸發順序,同樣是先進先出的佇列結構 ( Queue )
- Event Loop: 持續調度 Call Stack 與 Callback Queue 之間狀態的機制,當 Call Stack 為空時,會抓取 Callback Queue 最上層任務,到 Call Stack 去執行。
「也就是說,Event loop 是 stack 和 queue 之間的橋樑,讓執行緒永遠有事做~(誤」
資源補充,強烈推薦觀看影片介紹,會有看完整的理解:
講者做的簡化機制的 demo : http://latentflip.com/loupe
好拉~ Event Loop 的淺談就差不多到這結束了,
以下為 JS 引擎內部實作的再進一步的討論,沒興趣的可就此打住~
JS 引擎進階討論:
Ignition: compiles JavaScript functions to a concise ( bytecode 將程式碼 compile 成 bytecode
TurbonFan: optimizing compilers ( 優化程式碼的 compiler
經由優化,優化成 machine code
AST: Abstract Syntax Tree
Reference:
https://v8.dev/blog/ignition-interpreter
https://v8.dev/blog/turbofan-jit
Call stack Reference:
JavaScript Event Loop And Call Stack Explained
內文有視覺化程式,可更幫助理解
The call stack is a mechanism that helps the JavaScript interpreter to keep track of the functions that a script calls.
Every time a script or function calls a function, it’s added to the top of the call stack. Every time the function exits, the interpreter removes it from the call stack.
A function either exits through a return statement or by reaching the end of the scope.