JavaScript 的 事件循环(Event Loop) 和 作业队列(Job Queue) 是理解异步执行的核心机制。
console.log("1"); // 同步
setTimeout(() => {
console.log("2"); // 宏任务
}, 0);
Promise.resolve().then(() => {
console.log("3"); // 微任务
});
console.log("4"); // 同步
// 输出顺序:1 → 4 → 3 → 2
执行步骤:
console.log("script start"); // 1. 同步
setTimeout(function () {
console.log("setTimeout"); // 6. 宏任务
}, 0);
Promise.resolve()
.then(function () {
console.log("promise1"); // 3. 微任务
})
.then(function () {
console.log("promise2"); // 4. 微任务
});
queueMicrotask(() => {
console.log("queueMicrotask"); // 5. 微任务
});
console.log("script end"); // 2. 同步
// 输出顺序:
// script start
// script end
// promise1
// promise2
// queueMicrotask
// setTimeout
setTimeout(() => console.log("timeout"));
setInterval(() => console.log("interval"));
requestAnimationFrame(() => console.log("raf"));
// I/O 操作
// UI 渲染
Promise.then/catch/finally
async/await(底层是Promise)
queueMicrotask()
MutationObserver
process.nextTick(Node.js)
// 示例1:微任务中的微任务
Promise.resolve()
.then(() => {
console.log("promise1");
Promise.resolve().then(() => console.log("promise inner"));
})
.then(() => {
console.log("promise2");
});
// 输出:promise1 → promise inner → promise2
// 示例2:混合执行
setTimeout(() => console.log("timeout1"));
Promise.resolve().then(() => {
console.log("promise1");
setTimeout(() => console.log("timeout in promise"));
});
setTimeout(() => console.log("timeout2"));
Promise.resolve().then(() => console.log("promise2"));
// 输出顺序:
// promise1 → promise2 → timeout1 → timeout2 → timeout in promise
// Node.js 示例
setImmediate(() => console.log("immediate"));
setTimeout(() => console.log("timeout"), 0);
Promise.resolve().then(() => console.log("promise"));
process.nextTick(() => console.log("nextTick"));
// 可能的输出:
// nextTick → promise → timeout → immediate
// 危险:微任务死循环
function infiniteMicrotasks() {
Promise.resolve().then(infiniteMicrotasks);
}
// 这会阻塞渲染!
// 正确:使用宏任务拆分
function processChunk() {
// 处理一部分数据
if (还有数据) {
setTimeout(processChunk, 0); // 让出控制权
}
}