從動圖輕鬆入門非同步 JavaScript(第一章)
了解非同步 JavaScript 背後如何運作
瀏覽器執行環境中的 JavaScript 是單線程的,也就是一次只能執行一件事,通常這不是什麼問題,但假設目前有一個超~~繁瑣的事件要處理 30 秒,或是去索取一個未知要多少時間的外部資源,如此一來其他事情就都會被擱置在後,讓使用者等待。
這是非常大的問題,但解決方法也非常的簡單:「不要呆呆站在那裏等!」。
假設訂了外送,會乖乖的等到外送員到家後吃飯,還是先做其他事情呢?想必是後者,那麼同樣的道理,各種不同的執行環境(runtime) 也提供了 JavaScript 自身並不存在的功能來處理非同步的操作,像是瀏覽器中有: Web API ,可以輕鬆創造非同步、避免事件阻塞的網頁。
圖解專有名詞
Call Stack:處理事情,就像在吃鬆餅
回到 JavaScript 引擎本身,當調用一個函式時,函式會被加入到一個叫做:「Call Stack」的 STACK (堆疊)之中,想像成吃鬆餅一樣,鬆餅(函式)由最上方加入然後再由上方開始吃掉(處理),代碼由上而下執行將函示推入執行推疊中,當被執行完就會離開。
Web API:瀏覽器提供的非同步好幫手
而處理非同步事件很常遇到的:fetch
、seTimeout
、addEventListener
都是由 Web API 所提供的方法,使用這些方法傳入的回呼函數將會交由 Web API 處理,因此 Call Stack 才能迅速被清空,處理下一個事件,不阻塞 JavaScript 的執行。
Callback Queue:等待入場的隊伍
Web API 的事項處理完成後並不會馬上返回 Call Stack 被執行,而是會被放入 Callback Queue 中等待。這樣也造成了像是 setTimeout
或 setInterval
並不會「準確的」如同描述的時間內被執行,而是單純在描述時間後會被加入 Callback Queue。
Event Loop:連結整個流程
那麼 Callback Queue 中的事項要如何被執行呢? 就輪到 Event Loop 出場的時候了,它只有也僅有一個功能:「連接 Callback Queue 與 Call Stack」。具體來說,當 Call Stack 是空的,第一個 Callback Queue 的事項就會被放入 Call Stack 中,
結語
希望經過簡單的動圖,可以更直觀快速的了解到非同步 JavaScript 背後究竟發生了什麼事。
參考資料
- DEV - JavaScript Visualized: Event Loop
- JSConf - What the heck is the event loop anyway?
- JSConf - In The Loop - setTimeout, micro tasks, requestAnimationFrame, requestIdleCallback
- Loupe - 圖示化了解非同步 JavaScript 背後運作