iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
Modern Web

小白大戰基礎網頁開發系列 第 13

D13 - Event Loop 基本須知 (下)

  • 分享至 

  • xImage
  •  

昨天大致了解為什麼我們需要 Event Loop, 為什麼 Event Loop 很重要以及該如何運用它後, 今天我們要繼續來看 Event Loop 更詳細的運作方式和例子。

Event Loop Review

為什麼會說學網頁開發的你不可不知 Event Loop 呢? 因為 Event Loop 可以說是 born for web browser !
還記得 JavaScript 單線程 運行嗎? 假設 web broswer 一次只能執行一件任務的時候, 當由第三方(e.g. Facebook,Google...)提供的 API 要在你的網站上使用它時, 而 web broswer 等待回應時, 畫面就處在一個顯示的階段, 呈現出 畫面卡住 (blocking) 的樣子。

Credit: https://www.pinterest.com/pin/842454674026547365/
Credit: https://www.pinterest.com/pin/842454674026547365/

這時候, 就是 Event Loop 華麗出場的時刻了, 像交通指揮警察來管控各方的車流, 防止交通阻塞stuck/blocking。Event Loop 是要確保每項任務可以順暢的運行, 我們可以把它想像成一個駐守於 web browser 裡的 Event Listener (事件監聽器)

Credit: https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5
Credit: https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5

Event Loop 的工作: 監控 Call StackCallback Queue。如果 Call Stack 為空,Event Loop 將從 queue (隊伍) 中拿取第一個事件並將其推送到 Call Stack,將由 Call Stack 有效地運行此事件任務。

Event Loop and its Friends

Credit: https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5
Credit: https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5

Call Stack 在前面介紹過了, 那麼讓我們來讀讀 Web APIs & Callback Queue

Web APIs:
我們所知道的 APIs, 比如 TimeOut, DOM, AJAX…
之後我們也會提到的 setTimeout(), 當其內部執行完後, 即會將事件任務交給 Callback Queue 去排隊處理, 實現 Concurrency (並發性) , 也就是 Multi-thread (多線程), 能夠 同時處理多項任務

Callback Queue:
與 Call Stack 相反, 它是 FIFO (First In, First Out), 先進先出, 像在銀行排隊一樣, 先來的先接受到銀行業務服務。
在 Event Loop 的監控下, callback queue 在 Event Loop 的指示下等待 Call Stack 中的項目執行完畢後, 才會把 callback queue 排隊的任務放到 call stack 中去執行。

Event Loop 實作例子

  1. set setTimeout(() => {}), 0)

    const bar = () => console.log('bar') const baz = () => console.log('baz') const foo = () => { console.log('foo') bar() baz() } foo()

Result:

foo
bar
baz

Credit: https://flaviocopes.com/javascript-event-loop/
Credit: https://flaviocopes.com/javascript-event-loop/

單純用文字講述可能會有點抽象, 在看完清楚明瞭的 Event Loop 流程圖後, 應該會比較有概念了! 接下來看一個比較複雜一點的…

  1. Challenge: 每個事件都是一個 function callback

    console.log('Hi'); setTimeout(function cb1() { console.log('cb1'); }, 5000); console.log('Bye');

Result:

Hi
Bye
cb1
  1. 瀏覽器控制台無任務, call stack 為空

  2. console.log('Hi') 被添加到 call stack

  3. console.log('Hi') 被執行了

  4. console.log('Hi') 從 call stack 被移除了

  5. setTimeout(function cb1() { ... }) 被添加到 call stack

  6. setTimeout(function cb1() { ... }) 被執行了, 瀏覽器使用了 Web APIs → timer, 負責處理倒數計時

  7. setTimeout(function cb1() { ... }) 倒數完成後, 從 call stack 中被移除

  8. console.log('Bye')被添加到 call stack

  9. console.log('Bye')被執行了

  10. console.log('Bye') 從 call stack 中被移除

  11. 5 秒後,計時器完成倒數並將 cb1 callback 推送到 callback queue

  12. 在 Event Loop 的監控下, 它把 cb1 從 callback queue 中拿出, 並放置到 call stack 中

  13. cb1 被執行且添加 console.log('cb1') 到 call stack 中

  14. console.log('cb1') 被執行了

  15. console.log('cb1') 從 call stack 中移除

  16. cb1 從 call stack 中被移除

參考資料: https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5

最後要跟大家力推一個讓你可以清楚觀看操作 Event Loop, Call Stack, Callback Queue, JS 執行環境 (Runtime) 動態流程的學習材料: Loupe by Philip Roberts


上一篇
D12 - Event Loop 基本須知 (上)
下一篇
D14 - 更多關於 JS Events 的那些小事
系列文
小白大戰基礎網頁開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言