iT邦幫忙

2023 iThome 鐵人賽

DAY 10
1
自我挑戰組

複習 JavaScript 核心概念系列 第 10

[Day 10] 非同步任務的兩種類型:Macrotask 與 MicroTask

  • 分享至 

  • xImage
  •  

昨天提到了瀏覽器中 事件循環(Event Loop) 整體的運作過程,但其中有個地方沒有深入介紹,那就是MacrotaskMicroTask

注意,接下來會提到多種非同步操作,例如計時器(setTimeout、setInterval)PromiseDOM事件處理(例如滑鼠點擊、鍵盤輸入的監聽器)非同步函數(async 和 await)等等。本篇文章並不會詳述這些非同步操作的用法,而會聚焦到今天的主題 MacrotaskMicroTask 的差別與運作流程。

另外今天算是延續昨天事件循環(Event Loop) 的概念,最好先理解一下。


開始今天的主題,在事件循環中的 Callback Queue 中,
其實可以看成有兩條佇列:Macrotask(宏任務)Microtask(微任務)
非同步操作會依照類型不同而被排入兩條佇列的其中一條;而他們又會依照彼此的優先度而被取出執行。

Macrotask(宏任務)

Macrotask 是一個較大、較長的非同步任務,且在事件循環中具有較低的優先度。
例如:計時器(setTimeOut、setInterval),使用者互動(事件監聽器的 callback)等。

Microtask(微任務)

Microtask 是一個較小、較短的非同步任務,它的優先度較高,會在 Macrotask 之前執行。
例如:Promise 的thencatch、async function、process.nextTick()等。


以下是 Event Loop 處理 MacrotaskMicrotask 流程圖(未知原始圖片來源)

上圖簡單來說,必須等所有的 microtask 佇列清空,才會檢查 macrotask 佇列並取出一個項目並執行。
但每執行完一個 macrotask ,都會再檢查 microtask 佇列並等待當下的 microtask 佇列清空,才會再回頭檢查 macrotask 佇列。

用動圖更好理解:


以下是一個實際的例子。

console.log('Start');
    
setTimeout(() => console.log('SetTimeout checked!'), 0);

Promise.resolve().then(() => console.log('Promise checked!'));

console.log('End');

而它們輸出順序的結果為:

Start
End
Promise checked!
SetTimeout checked!

首先我們知道setTimeoutPromise 都是非同步操作。
但因為 setTimeout 屬於 MacrotaskPromise 屬於 Microtask
因此雖然 setTimeout 的回調函式先進入了 Callback Stack
Promise 具有較高的優先級,
所以會先印出「Promise checked!」後才印出「SetTimeout checked!」。


總結

今天介紹了非同步操作依類型會被分為 MacrotaskMicroTask
MicroTask 的優先度高於 Macrotask,所以 事件循環(Event Loop) 在檢查 Call Stack 時會優先取出 MicroTask 並執行。

那麼今天就到這邊了,明天見 ~


上一篇
[Day 09] 不可不知的事件循環(Event Loop)
下一篇
[Day 11] JavaScript 可以不加分號?關於「自動分號插入(ASI)」
系列文
複習 JavaScript 核心概念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言