JavaScript Event loop 三歲小孩解釋法!
三歲小孩解釋版的 Event Loop
想像你在玩一個「煮泡麵」的遊戲,你有一個超級忙碌的廚房,但這個廚房 一次只能做一件事(這就是 JavaScript 的「單執行緒」)。
1. 同步(Synchronous)—— 一件事做完才能做下一件
你開始煮泡麵:
先把水倒進鍋子
開火加熱水
水滾了再放泡麵
等 3 分鐘
泡麵煮好了,關火,開吃!
這就是 同步,所有事情都要 一件做完才做下一件,如果等水滾的時候什麼都不能做,那就超級無聊!
2. 異步(Asynchronous)—— 可以同時做別的事
但是你發現:「為什麼要乾等 3 分鐘?」所以你決定利用時間去做其他事情:
把水倒進鍋子,開火煮水(這需要時間)
等水滾的時候,先去洗碗
再去切小菜
等水滾了,把泡麵放進去(繼續等)
再去倒飲料
泡麵好了,關火,開吃!
這就是 異步,你可以一邊等水滾,一邊做別的事情,不會浪費時間。
3. Event Loop(事件循環)—— 廚房小助手
但是,怎麼確保泡麵不會煮到忘記呢?這時候你的 小助手「事件循環」 就會幫你看著鍋子:
如果水還沒滾,繼續做別的事
一旦水滾了,小助手提醒你:「水滾了!該放泡麵了!」
之後再提醒你:「3 分鐘到了!泡麵好了!」
這就是 事件循環(Event Loop),它的工作就是:
先把該做的事情 (同步的事) 做完
然後去看有沒有事情 (異步的事) 完成了
如果有,就趕快去做!
4. 宏任務(Macro Task)和微任務(Micro Task)—— 事情的優先順序
但有時候,你的事情還有「重要性」的差別,比如:
微任務(Micro Task):超級緊急的事情,例如「先加調味粉」,這些事情 一定要馬上做!
宏任務(Macro Task):普通的事情,例如「等 3 分鐘」,這種事情可以排隊等一下。
所以 JavaScript 會先做「微任務」,再做「宏任務」。
舉例:
js複製編輯console.log(1);
setTimeout(() => {
console.log(2);
}, 0);
Promise.resolve()
.then(() => {
console.log(3);
})
.then(() => {
console.log(4);
});
輸出順序是:
複製編輯1
3
4
2
因為:
console.log(1)
直接執行setTimeout
是 宏任務,所以等一下Promise.then
是 微任務,所以 比 setTimeout 先執行!console.log(3)
和console.log(4)
先執行完 微任務console.log(2)
最後才執行(因為setTimeout
在 下一輪 才跑)
5. requestAnimationFrame 和 requestIdleCallback
requestAnimationFrame
:瀏覽器畫面更新前執行(畫圖前的準備)requestIdleCallback
:等瀏覽器有空再執行(等於「有空再來做」)
總結
事件循環就像一個 廚房小助手,會幫你安排事情:
先做同步的事(直接執行)
遇到異步的事,讓它排隊
先處理 微任務
再來處理 宏任務
重複這個過程,讓程式運作流暢不卡住!
這樣懂了嗎?😆