iT邦幫忙

2021 iThome 鐵人賽

DAY 9
0
自我挑戰組

登堂入室!前端工程師的觀念技術 _30_ 題系列 第 9

8. 解釋 Event Loop ( 下 ) --- Task Queue ( Callback Queue )

(上一篇只有複習,沒有帶到題目,所以這篇會解釋兩個問題,答案可以直接看結論~)

  1. 解釋Event Loop的運作?
  2. Call Stack和Task Queue的差異?

在上一篇文章 7. 解釋 Event Loop ( 上 ) --- Call Stack有提到,非同步的程式設計是為了解決單執行緒在事件的處理上,沒有效率的問題。

而這篇文章的主題 —— Event Loop,就是用來控制在JS裡同步與非同步事件的運行:

Event Loop 事件循環


https://ithelp.ithome.com.tw/upload/images/20210909/20129476TQdN4y0K6I.png
(以 Google Chrome的V8引擎為例。 )

解釋一下這張圖:

  1. JavaScript Engine本身涵蓋兩個Components:

    • Memory Heap — 決定object在記憶體的配置。
    • Call Stack — 程式碼運行時,放置 stack frames 的地方。(負責排序同步執行函式)
  2. 許多我們在瀏覽器使用的API(e.g. DOM, AJAX, Timeout...),並非來自JS引擎,而是由瀏覽器的 Web APIs 提供。

  3. 所有被放進Async Function裡,作為參數的function,被稱作"callback",這些callback被依序放在 callback queue 等待執行。(負責排序非同步執行函式)

所有執行環境的共通點,就是都有一個叫"event loop"的內建機制。
它會隨著時間執行上述被分類的任務,並在每次執行時調用JS引擎。

Event Loop最重要的工作,就是控制 Call StackCallback Queue(Task Queue) 的運作。

( ↑ 全文重點

+++++++++++++++++++++++++
整理一下邏輯關係:

  • Chrome(或Node.js)使用 V8 引擎;V8 引擎包含: Memory Heap 和 Call Stack。
  • 各個 Browser 提供 Web APIs 供開發者使用;Web APIs 包含 DOM, AJAX, setTimeout...等。

+++++++++++++++++++++++++

Web APIs & Callback Queue(Task Queue)


我們已經知道DOM, AJAX, Timeout...都是由Web APIs提供的API,而當我們使用這些API進行非同步的呼叫(callback function),
Event Loop 會將 callback function 放進 Callback Queue (佇列)。

( 我自己在解釋的時候偏好講Callback Queue,但因為題目寫Task Queue,所以下面結論是講Task Queue。)

Queue 佇列

佇列也是資料結構的一種,特色是先進先出(First-In-First-Out, FIFO)。
https://ithelp.ithome.com.tw/upload/images/20210909/20129476cJEyjuMT9W.png
假設物件依照a, b, c的順序被放入,越早放入的會越早取出,所以取出的順序也是a, b, c。

Callback Queue

A JavaScript runtime uses a message queue, which is a list of messages to be processed. Each message has an associated function which gets called in order to handle the message.

→ 直到Call Stack被清空,Event Loop會將Callback Queue裡最早紀錄的訊息(message)放入Call Stack,直到Callback Queue裡的message也被清除完成。

這裡可以執行一個例子:

    console.log('start');

    setTimeout(function callback() { 
        console.log('callback is here');
    }, 3000);

    console.log('end');

setTimeout()的執行方式
setTimeout()並不會直接將callback交給event Loop,他會先建造自己的計時器(timer),直到計時結束,才將將callback放進callback queue。

→ 因此,上面例子的3000不是指3秒後就會執行程式,而是3秒後才會被放進佇列

start
end

callback is here // 3秒後出現

然後上面的執行順序是這樣的: gif和圖檔(這次圖片放進來反而有點亂,所以和gif的連結放在一起。)

  1. 【In Call stack】 console.log('start')放進call stack;執行console.log('start')
  2. 【In web api】 setTimeout()建立timer,等3秒...
  3. 【In Call stack】console.log('end')放進call stack;執行console.log('end')
  4. 【In web api】3秒結束,callback()進入【Callback Queue】
  5. 【In Callback Queue】Call stack被清空,進入Call stack。
  6. 【In Call stack】 callback()放進call stack;執行callback()
【In Call stack】 【In web api】 【In Callback Queue】
1 console.log('start')放進call stack;執行console.log('start') --- ---
2 --- setTimeout(callback())建立timer,等3秒...
3 console.log('end')放進call stack;執行console.log('end') ---
4 --- --- 3秒結束,callback()進入【Callback Queue】
5 callback()放進call stack;執行callback()

結論

  1. 解釋Event Loop的運作?
    因為JS的執行是單執行緒的,在處理同步事件時,會將函式放在Call Stack執行。
    如果是請求資料或滑鼠點擊之類的非同步事件,則會將事件交給瀏覽器提供的Web APIs,在解析完成後,放到Task Queue,等待Call Stack裡的函式執行完畢後,再繼續將Task Queue裡的函式依序放入Call Stack,並完成剩餘函式。

  2. Call Stack和Task Queue的差異?
    Call Stack用於同步事件的函式執行,Task Queue用於非同步事件的函式執行,而Call Stack裡的工作會先被執行完畢。
    Call Stack的結構是後進先出(LIFO),越早放進Call Stack的函式會越晚被執行;而Task Queue則是先進先出(FIFO),被放進Task Queue的函式,會依照放入順序執行。

【如內文有誤還請不吝指教>< 謝謝閱覽至此的各位:D】

參考資料:

-----正文結束-----

我自己是會聽歌聽到捨不得去睡覺的人,所以事情做不完的時候,音樂放出來我就會乖乖做下去了。
前陣子才把《La La Land》補完,但在看電影之前就很喜歡《City Of Stars》這首歌。


上一篇
7. 解釋 Event Loop ( 上 ) --- Call Stack
下一篇
9. 關於 this 的 5 題練習
系列文
登堂入室!前端工程師的觀念技術 _30_ 題31

尚未有邦友留言

立即登入留言