事件循環是維護 JavaScript 程式碼執行順序(處理非同步操作而不阻塞主執行緒)的循環。
在深入事件循環之前需要了解的事情:
- 呼叫堆疊:這是 JavaScript 執行程式碼的地方。它遵循後進先出 (LIFO) 結構。當呼叫函數時,會建立一個新的執行上下文並將其推入堆疊。當功能結束時,它會彈出。
- MicroTasks 隊列:專用於queueMicroTask 方法、Promise 處理程序、特殊隊列回呼和MutationObserver(介面提供了監視 DOM 樹所做變更的能力)。
MacroTasks 隊列:來自Web API 的所有其他回調(
- setTimeout、setInterval、DOM API , fetch)進入巨集任務佇列。
什麼是事件循環?
這是一個無限循環,等待任務並將其推送到呼叫堆疊中執行。由於 JavaScript 是單執行緒的,它會維護一個執行順序來根據優先權處理同步非同步操作。
常規 JS 程式碼:- 同步程式碼首先運行並填入呼叫堆疊。
MicroTasks:- 在 microTasks 佇列中排隊的任務被執行。
MacroTasks:- 在 MacroTasks 佇列中排隊的任務被執行。
讓我們透過一個範例來更好地理解工作流程
// Programmatic way of how the event loop processes tasks
while (true) {
// Step 1: Execute tasks in the call stack
while (!callStack.isEmpty()) {
const currentTask = callStack.pop();
currentTask(); // Executes the task
}
// Step 2: Process all microtasks
while (!microTasksQueue.isEmpty()) {
const microTask = microTasksQueue.shift();
callStack.push(microTask); // Push microtask to call stack for execution
}
// Step 3: Process one macrotask if available
if (!macroTasksQueue.isEmpty()) {
const macroTask = macroTasksQueue.shift();
callStack.push(macroTask); // Push macrotask to call stack for execution
}
// Break if there's nothing left to process
if (callStack.isEmpty() && microTasksQueue.isEmpty() && macroTasksQueue.isEmpty()) {
break;
}
}
登入後複製
假設我們有 2 個隊列
1. setTimeout(() => console.log(1), 2000);
2. Promise.resolve().then(() => {
3. console.log(2);
4. queueMicroTask(() => console.log(3));
5. });
6. Promise.resolve().then(() => {
7. console.log(4);
8. setTimeout(() => console.log(5));
9. });
10. setTimeout(() => console.log(6));
11. console.log(7);
// 7 2 4 3 6 5 1
登入後複製
microTasks 和 macroTasks。當程式碼開始執行時,
-
()=> console.log(1) 在 2000 毫秒內被推入 macroTasks 佇列。
-
()=> { 控制台.log(2); queueMicroTask(() => console.log(3)); }) 被推入 microTasks 佇列。
-
()=> { 控制台.log(4); setTimeout(() => console.log(5)); }) 被推入 microTasks 佇列。
-
()=> console.log(6) 在 0 毫秒內被推入 macroTasks 佇列。
-
console.log(7) 執行並在控制台中列印 7。
- 現在事件循環檢查microTasks 佇列中的任務並採取() =>; { 控制台.log(2); queueMicroTask(() => console.log( 3)); }) 任務並在控制台中列印2 並推送() =>; console.log(3) 進入microTasks 隊列。
- 接下來,事件循環檢查microTasks 隊列並採取() =>; { 控制台.log(4); setTimeout(() => console.log(5 )); }) 任務並列印4 並推送() => console.log(5) 在0 毫秒內寫入macroTasks 隊列。
- 事件循環再次檢查microTasks佇列並採取() =>; console.log(3)) 任務並在控制台中列印 3。
- 由於 microTasks 佇列現在為空,事件循環檢查 MacroTaskQueue 並採取 () =>; console.log(6) 並在控制台中列印 6。
- 事件循環執行下一個任務() =>確保microTasks 佇列中沒有任何任務後,從macroTasks 中輸出console.log(5) 並在控制台中列印5 .
- 事件循環執行下一個任務 () =>來自 macroTasks 的 console.log(1) 並在控制台中列印 1。
感謝您的閱讀!我希望您覺得這個部落格內容豐富且引人入勝。如果您發現任何不準確之處或有任何回饋,請隨時告訴我。
以上是事件循環——JavaScript的詳細內容。更多資訊請關注PHP中文網其他相關文章!