在 javascript 事件循环中,宏任务(如 settimeout)和微任务(如 promise.then)通过不同的执行队列影响事件响应顺序。主线程执行完当前同步代码后,会先清空所有微任务队列,再取出一个宏任务执行,这种机制确保了高优先级的异步操作能尽快得到处理。

Promise 回调与 setTimeout 的执行顺序差异是什么
当 Promise 的 then 回调和 setTimeout 同时存在时,Promise 的回调会先于 setTimeout 执行。这是因为 Promise 的回调属于微任务,而 setTimeout 属于宏任务,事件循环在每轮宏任务结束后会优先处理微任务队列。

console.log('1');
setTimeout(function() {
console.log('2');
}, 0);
new Promise(function(resolve) {
console.log('3');
resolve();
}).then(function() {
console.log('4');
});
console.log('5');
上述代码的输出顺序为:1, 3, 5, 4, 2。首先输出同步代码 1 和 3、5;然后执行微任务 4;最后执行宏任务 2。
DOM 渲染时机如何受微任务队列影响
浏览器在每次宏任务执行完毕后、下一个宏任务开始前,会检查是否需要重绘或重排。如果微任务队列中有修改 DOM 的操作,这些操作会在渲染前完成,从而避免不必要的中间状态渲染。

document.body.innerHTML = 'start';
setTimeout(function() {
document.body.innerHTML = 'end';
}, 0);
new Promise(function(resolve) {
resolve();
}).then(function() {
document.body.innerHTML = 'promise';
});
在这个例子中,虽然 setTimeout 设置了 0 毫秒延迟,但 Promise 的微任务会在宏任务之前执行。因此,用户看到的最终结果是 'promise',而不是 'end',因为微任务修改了 DOM,且没有触发新的渲染周期来显示 'end'。
大量微任务堆积会导致什么后果
如果微任务队列中堆积了大量任务,它们会一直执行直到队列为空,这会导致当前宏任务被阻塞,进而延迟 UI 渲染和其他宏任务的执行。这种现象被称为“长任务”,可能导致页面卡顿。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











