在 javascript 事件循环机制中,promise 的回调函数通常比 settimeout 设置的定时器先执行。这一结论基于浏览器环境下的任务队列优先级:同步代码执行完毕后,会优先清空微任务队列(microtask queue),包括 promise 的 then/catch/finally 回调,随后才从宏任务队列(macrotask queue)中取出一个任务执行。理解这一机制有助于避免竞态条件并优化异步逻辑。

同步代码执行后的任务排队规则
JavaScript 引擎在执行脚本时,首先处理所有同步代码。当同步代码执行栈为空后,引擎会检查微任务队列。如果存在微任务(如 Promise 回调),则立即执行直到队列为空。只有当微任务全部处理完毕后,引擎才会从宏任务队列中取出一个任务(如 setTimeout 回调)放入执行栈。这意味着,即使 setTimeout 的延迟时间设置为 0,其回调也会排在所有同步代码和当前轮次的 Promise 回调之后执行。
// 示例代码:观察执行顺序
console.log('1. 同步代码开始');
setTimeout(() => {
console.log('2. setTimeout 回调');
}, 0);
Promise.resolve().then(() => {
console.log('3. Promise 回调');
});
console.log('4. 同步代码结束');
// 预期输出顺序:
// 1. 同步代码开始
// 4. 同步代码结束
// 3. Promise 回调
// 2. setTimeout 回调

微任务与宏任务的执行差异
微任务包括 Promise 回调、MutationObserver 等,而宏任务包括 setTimeout、setInterval、I/O 操作等。关键区别在于,微任务在当前事件循环轮次中被批量执行,直到队列为空;而宏任务每次只执行一个,执行完后可能触发新的微任务或宏任务,从而进入下一轮事件循环。这种设计确保了 UI 渲染等高优先级任务不会被过多的微任务阻塞,同时也保证了 Promise 链式调用的连贯性。
// 复杂场景:嵌套异步操作
console.log('Start');
setTimeout(() => {
console.log('Timeout 1');
Promise.resolve().then(() => {
console.log('Nested Promise in Timeout');
});
}, 0);
new Promise((resolve) => {
console.log('Promise 1 Start');
resolve();
console.log('Promise 1 End');
}).then(() => {
console.log('Promise 1 Then');
setTimeout(() => {
console.log('Nested Timeout in Promise');
}, 0);
});
console.log('End');
// 预期输出:
// Start
// Promise 1 Start
// Promise 1 End
// End
// Promise 1 Then
// Timeout 1
// Nested Promise in Timeout
// Nested Timeout in Promise
queueMicrotask 的入队顺序测试
除了 Promise,还可以使用 queueMicrotask API 将任务加入微任务队列。该 API 非 Node.js 专有,在现代浏览器中也广泛支持。通过对比 queueMicrotask 和 Promise 回调的执行顺序,可以进一步验证微任务队列的 FIFO(先进先出)特性。通常情况下,先入队的微任务会先执行,无论其是通过 Promise.then 还是 queueMicrotask 添加。
// 测试 queueMicrotask 与 Promise 的顺序
console.log('A');
queueMicrotask(() => {
console.log('B: queueMicrotask');
});
Promise.resolve().then(() => {
console.log('C: Promise');
});
queueMicrotask(() => {
console.log('D: queueMicrotask');
});
console.log('E');
// 预期输出:
// A
// E
// B: queueMicrotask
// C: Promise
// D: queueMicrotask
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











