事件循环(Event Loop)中setTimeout等异步API执行优先级差异原因
为什么setTimeout、Promise.then、requestAnimationFrame的异步回调执行优先级有差异
这三类回调的优先级差异本质是JavaScript事件循环对不同异步任务的队列划分和执行规则导致的,具体可以按所属任务队列的优先级排序理解:
- 微任务队列 优先级最高:
Promise.then的回调属于微任务,规则是当前上下文的所有同步代码执行完毕后,会立刻清空整个微任务队列,不会等待渲染或其他宏任务执行。 - 渲染前回调队列 优先级次之:
requestAnimationFrame的回调是浏览器专属的渲染前置队列,执行时机在所有微任务清空之后、浏览器执行重绘/重排之前,每轮事件循环最多执行一次该队列的所有回调。 - 宏任务队列 优先级最低:
setTimeout的回调属于宏任务,必须等当前轮次的微任务全部执行完成、渲染阶段的所有回调处理完毕后,才会在下一轮事件循环中被调度执行。
验证代码执行逻辑说明
你给出的代码实际运行的输出顺序是 4 → 5 → 2 → 3 → 1,逐行对应执行逻辑如下:
setTimeout(()=>console.log(1)); // 推入宏任务队列,最后执行 Promise.resolve(2).then(console.log); // 推入微任务队列,同步代码跑完后立刻执行 requestAnimationFrame(()=>console.log(3)); // 推入渲染前置队列,微任务清空后执行 console.log(4); // 同步任务,第一个输出 window.onclick = ()=>console.log(5); // 绑定点击事件回调 window.dispatchEvent(new Event('click')); // 同步触发事件,回调属于同步执行逻辑,第二个输出
执行步骤拆解:
- 先执行所有同步代码:输出4,同步触发点击事件输出5,同步阶段结束。
- 清空当前微任务队列:执行Promise.then回调,输出2。
- 进入浏览器渲染前置阶段:执行requestAnimationFrame回调,输出3。
- 本轮事件循环结束,进入下一轮调度,处理宏任务队列中的setTimeout回调,输出1。
内容的提问来源于stack exchange,提问作者trigold
相关产品推荐
相关产品推荐

