JavaScript 的事件循环(Event Loop)机制是其异步编程模型的核心。它负责处理宏任务(macro tasks)和微任务(microtasks)的执行顺序。理解这一点对于编写高效的异步代码至关重要
宏任务(Macro Tasks)
宏任务是 JavaScript 中的主要任务类型,它们包括以下几种:
- setTimeout
- setInterval
- I/O 操作
- UI 渲染
- 用户事件(例如点击事件)
- fetch 请求
- XMLHttpRequest
宏任务的特点是它们会阻塞其他任务的执行,直到当前宏任务完成。每个宏任务都会创建一个新的执行上下文,并且在执行完当前宏任务之前,不会执行其他宏任务。
微任务(Microtasks)
微任务是在当前宏任务执行完毕后立即执行的任务,而不是等待下一个宏任务开始。它们包括:
- Promise 的 .then 回调
- process.nextTick(Node.js 中)
- MutationObserver(浏览器中)
微任务的特点是它们会在当前宏任务执行完成后立即执行,但在下一个宏任务开始之前。
事件循环流程
-
执行栈:JavaScript 是单线程的,所有的同步任务都在执行栈中执行。 任务队列:宏任务和微任务分别有自己的队列。
-
微任务队列:每当执行栈为空时,就会执行微任务队列中的所有任务。
-
宏任务队列:当执行栈为空并且微任务队列也为空时,事件循环会从宏任务队列中取出下一个宏任务执行。
示例
下面是一个简单的示例,展示宏任务和微任务的执行顺序:
console.log('Start');
Promise.resolve().then(() => {
console.log('Promise1');
setTimeout(() => {
console.log('setTimeout2');
}, 0);
});
setTimeout(() => {
console.log('setTimeout1');
Promise.resolve().then(() => {
console.log('Promise2');
});
}, 0);
console.log('End');
输出顺序
- Start
- End
- Promise1
- setTimeout1
- Promise2
- setTimeout2
解释
- 同步任务:首先输出 “Start” 和 “End”。
- 微任务:执行栈清空后,执行微任务队列中的 Promise1。
- 宏任务:执行宏任务队列中的 setTimeout1,输出 “setTimeout1”。
- 微任务:执行栈再次清空后,执行微任务队列中的 Promise2。
- 宏任务:执行宏任务队列中的 setTimeout2,输出 “setTimeout2”。
这就是 JavaScript 中宏任务和微任务的基本工作原理。如果你有任何更具体的问题或者需要进一步的解释,请随时告诉我!