iT邦幫忙

0

Macrotask vs Microtask 常搞錯的部分

  • 分享至 

  • xImage
  •  

今天來講 Macrotask vs Microtask 大家可能常搞錯的部分

這邊我先簡單介紹一下 Event Loop,並在文章後面會有附上相關連結,有興趣的讀者可以自己去研究一下

Event Loop

由於 JS 本身是 單線程序(single-threaded),代表一次只能有一件事能被執行,所以當出現一個很大的計算的時候,就會導致後面的計算沒辦法被執行。並且如果計算時間多過於 16.6 ms 的話,畫面就會出現卡頓,所以我們將這些計算移到背景去執行,這個機制就叫 Event Loop

瀏覽器的運行機制

當今天瀏覽器在運行 javaScript 程式碼時,會產生一個東西叫做 Execution Context(執行上下文),並會分成兩個部分: creation phase, execution phase

creation phase 會產生四個步驟:

  1. 創建 global object。( 如瀏覽器中的window object,或Node.js中的 global object。)
  2. 建立 scope (依照 closure 這個準則)。
  3. 創建 this object,並被綁定至 global object。
  4. 將 variables 和 function 分配至記憶體,並初始化為 undefined。(這也是所謂的hoisting。)

execution phase 會有以下步驟:

  1. 變數 會被賦予值,
  2. function 會被執行

這邊因為要討論的部分不是 Execution Context,所以這邊就不做太多的著墨,有興趣的讀者可以參考這篇文章

Macrotask vs Microtask

現在要來講一下今天的主題: Macrotask vs Microtask,這兩個行為會是發生在 execution phase 期間

我們都知道當 javaScript 執行到需要非同步的程式碼時,會把這個需要非同步的程式碼先放到 task queue 中,並且繼續執行其他程式碼,待其他程式碼都執行完成後,才會回到 task queue 中,將 task queue 中的 function 丟回到 call stack 上來執行

如果想看動畫版的執行順序,可以參考這個 Project

但即使都是非同步的程式碼,卻還是有執行的先後順序,主要分成兩個部分:

  • Macrotask: Web API (setTimeout, setInterval, ….)

  • Microtask: Promise

在了解先後順序前,我想先請各位讀者試著先研究一下下方程式碼會 alert 出什麼結果

setTimeout(() => alert("setTimeout"));

Promise.resolve()
  .then(() => alert("Promise"));

alert("global");

答案是: global => Promise => setTimeout

你是否答對了呢?

恭喜,所以我們現在可以知道執行順序是: Microtask => Macrotask

但是,其實執行順序是: Macrotask => Microtask,等等,那為什麼印出來的結果是: global => Promise => setTimeout,而不是: global => setTimeout => Promise

原因是這樣的,當頁頁面開啟時,載入對應的 JS 檔並且執行這件事情,就是一個 Macrotask

所以當 第一個 Macrotask 執行完成後,會去把所有的 Microtask 執行完,才會去執行第二個 Macrotask

Immediately after every macrotask, the engine executes all tasks from microtask queue, prior to running any other macrotasks or rendering or anything else.

以下放上示意圖

Macrotask -> All Microtask -> Macrotask

按照上面的示意圖,我們回到程式碼,就會長這樣:

Macrotask(載入對應的 JS 檔) -> All Microtask (Promise) -> Macrotask (setTimeout)

結論

這邊幫各位整合幾個結論:

  1. 執行順序是: Macrotask => Microtask
  2. 當頁面載入要執行 JS 的這件事情,就會是一個 Macrotask
  3. 當一個 Macrotask 執行完成,會馬上執行所有的 Microtask,結束後才會去執行下一個 Macrotask

以上就是今天的文章,希望有幫助到大家,那我們下次見,拜拜

(有任何問題或是想討論的地方,都歡迎留言、或是私訊我,謝謝)
有興趣的朋友可以追蹤我的 Medium

參考文章:
https://ithelp.ithome.com.tw/articles/10296041
https://ithelp.ithome.com.tw/articles/10222737
https://javascript.info/event-loop


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言