iT邦幫忙

1

JS - 非同步機制

  • 分享至 

  • xImage
  •  

考慮下方程式碼,你覺得輸出會是什麼呢?

console.log("1");

setTimeout(() => {
  console.log("2");
}, 0);

Promise.resolve()
  .then(() => {
    console.log("3");
  })
  .then(() => {
    console.log("4");
  });

console.log("5");

這五個輸出,來自四種不同的機制、形式,而JS的引擎,遵守這個優先層級法則在執行,因此這篇我們要來聊聊,關於:呼叫堆疊(Call Stack)巨任務(Macro-task)微任務(Microtask),以及負責協調全場的 事件循環(Event Loop)

1. 呼叫堆疊(Call Stack)

Call Stack 是一個遵循 LIFO(後進先出,Last In, First Out) 原則的資料結構。你可以把它想像成疊盤子:你最後放上去的盤子,必須第一個拿下來。

JS 是單執行緒的,代表它一次只能做一件事。當你的程式執行一個函式時,JS 引擎就會把它「推(Push)」進 Call Stack 開始執行;如果函式裡面又呼叫了另一個函式,就會再疊上去。當函式執行完畢,就會被「彈出(Pop)」堆疊。

function third(){
  console.log("3");
}

function second(){
  third();
  console.log("2");
}

function first(){
  second();
  console.log("1");
}

first();
  • 輸出結果3 -> 2 -> 1

2. 巨任務(Macro-task)與 微任務(Microtask)

當非同步事件發生時,任務會被丟到不同的「排隊佇列(Queue)」裡。

巨任務(Macro-task / Task)

  • 常見成員setTimeoutsetInterval、I/O 操作、UI 渲染。
  • 特點:處理較大、較重的非同步任務。每次事件循環只會處理一個巨任務。

微任務(Microtask)

  • 常見成員Promise.then / catch / finallyqueueMicrotask
  • 特點:通常是需要「盡快處理」的小任務。它的優先級極高——只要 Call Stack 一空,微任務佇列會被全部清空,才會輪到下一個巨任務。

3. 事件循環(Event Loop)

Event Loop 的工作非常純粹但極其重要,它不斷重複做這件事(像個無限迴圈):

  1. 檢查 Call Stack:看看裡面的同步任務有沒有跑完。
  2. 如果 Call Stack 是空的
    • 優先檢查 微任務佇列(Microtask Queue),把裡面的任務全部搬進 Call Stack 執行完畢。
    • 微任務清空後,檢查 巨任務佇列(Macro-task Queue),把裡面最舊的一個任務搬進 Call Stack 執行。
  3. 重複以上步驟。

4. 解釋範例:

console.log("A: 同步任務 1");

setTimeout(() => {
  console.log("B: 巨任務 (setTimeout)");
}, 0);

Promise.resolve()
  .then(() => {
    console.log("C: 微任務 1 (Promise)");
  })
  .then(() => {
    console.log("D: 微任務 2 (Promise)");
  });

console.log("E: 同步任務 2");

逐步拆解:

  1. 同步階段
    • 印出 A: 同步任務 1
    • 遇到 setTimeout -> 丟進巨任務佇列。
    • 遇到 Promise -> 它的第一個 .then 丟進微任務佇列。
    • 印出 E: 同步任務 2
    • 目前輸出AE
  2. 微任務階段(Call Stack 空了,全面清空微任務)
    • 執行微任務 1 -> 印出 C: 微任務 1 (Promise),同時產生了微任務 2,也塞進微任務佇列。
    • 執行微任務 2 -> 印出 D: 微任務 2 (Promise)
    • 目前輸出AECD
  3. 巨任務階段(微任務清空後,跑一個巨任務)
    • 執行 setTimeout -> 印出 B: 巨任務 (setTimeout)
    • 最終輸出A -> E -> C -> D -> B

圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言