首頁 > web前端 > js教程 > 深入探討非同步:微任務、巨集任務與事件循環

深入探討非同步:微任務、巨集任務與事件循環

Linda Hamilton
發布: 2025-01-01 08:23:10
原創
994 人瀏覽過

Deep Dive in Asynchrony: Microtasks, Macrotasks, and the Event Loop

JavaScript 的非同步特性在您深入研究其機制之前可能會讓人感覺很神奇。秘密在於它的事件循環,它協調兩個關鍵角色:微任務宏任務。但它們是什麼、它們如何運作以及為什麼它們重要?讓我們透過深入研究、範例和技巧來解開這個謎團,以掌握這個概念。


事件循環與任務佇列

JavaScript 引擎在單一執行緒中執行程式碼。為了處理非同步操作,它依賴事件循環,它在呼叫堆疊和任務佇列之間進行協調。這些任務隊列分為兩類:微任務宏任務

微任務

微任務是高優先權任務,必須在目前執行的 JavaScript 程式碼完成且呼叫堆疊為空時立即執行。它們確保快速的後續行動和一致的狀態。常見範例包括:

  • 承諾(.then,非同步/等待)
  • MutationObserver 回呼

宏任務

巨集任務是優先順序較低的任務,事件循環僅在所有微任務執行完畢後才處理。它們處理更大的、延遲的操作和外部事件。常見範例包括:

  • 計時器(setTimeout、setInterval)
  • 訊息頻道回呼
  • I/O 操作

還有 requestAnimationFrame,它不屬於任一佇列。它與瀏覽器的渲染週期同步,非常適合流暢的動畫。


如何運作

以下是事件循環處理任務的方式:

  1. 先執行同步程式碼。
  2. 清除微任務隊列
  3. 執行宏任務佇列中的一項任務。
  4. 重複步驟 2 和 3,直到處理完所有任務。

這種優先順序確保先解決諸如承諾之類的高優先級任務,然後再解決諸如計時器之類的不太緊急的操作。


實際應用範例

下面是一個實用的程式碼片段,用來說明同步程式碼、微任務、巨集任務和 requestAnimationFrame 之間的互動:

console.log('Synchronous code starts');

// Macrotask: setTimeout
setTimeout(() => {
  console.log('Macrotask: setTimeout');
}, 0);

// Macrotask: setInterval
const intervalId = setInterval(() => {
  console.log('Macrotask: setInterval');
  clearInterval(intervalId);
}, 100);

// Microtask: Promise
Promise.resolve().then(() => {
  console.log('Microtask: Promise then 1');
  Promise.resolve().then(() => {
    console.log('Microtask: Promise then 2');
  });
});

// Microtask: MutationObserver
const observer = new MutationObserver(() => {
  console.log('Microtask: MutationObserver');
});
const targetNode = document.createElement('div');
observer.observe(targetNode, { attributes: true });
targetNode.setAttribute('data-test', 'true');

// Macrotask: MessageChannel
const channel = new MessageChannel();
channel.port1.onmessage = () => {
  console.log('Macrotask: MessageChannel');
};
channel.port2.postMessage('Test');

// requestAnimationFrame
requestAnimationFrame(() => {
  console.log('Outside task queues: requestAnimationFrame');
});

console.log('Synchronous code ends');
登入後複製

預期輸出

輸出序列有助於闡明優先順序:

  1. 同步程式碼:「同步程式碼開始」、「同步程式碼結束」
  2. 微任務
    • 「微任務:承諾然後 1」
    • 「微任務:先承諾 2」
    • 「微任務:MutationObserver」
  3. 宏任務
    • 「宏任務:setTimeout」
    • 「巨集任務:MessageChannel」
    • 「宏任務:setInterval」
  4. requestAnimationFrame:「任務佇列外部:requestAnimationFrame」

深入探討:微任務與宏任務

微任務:關鍵特徵

  • 同步程式碼完成後立即執行。
  • 非常適合小型、高優先級的更新,例如解決承諾或對 DOM 突變做出反應。
  • 範例:Promise、MutationObserver。

宏任務:關鍵特徵

  • 僅在清除所有微任務後運行。
  • 用於較大、優先順序較低的操作或外部事件處理。
  • 範例:計時器、訊息通道。

requestAnimationFrame:奇怪的一個

雖然不是任務佇列的一部分,requestAnimationFrame 在非同步中發揮著獨特的作用。它安排程式碼在下一次瀏覽器重繪之前運行,確保最少的幀丟失和更流暢的動畫。


結論

微任務、巨集任務和事件循環之間的交互作用是 JavaScript 非同步的核心。透過理解和利用這些概念,您可以編寫更有效率、可維護和高效能的程式碼。請記住:首先是微任務,其次是巨集任務,然後使用 requestAnimationFrame 進行視覺美化。快樂編碼!

以上是深入探討非同步:微任務、巨集任務與事件循環的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板