关键在于理解事件循环规则:同步代码执行完后必须清空微任务队列,再执行下一个宏任务;每个script、settimeout回调、事件处理函数均为独立宏任务;promise构造器内代码同步执行,.then()才是微任务;async/await中await后代码均入微任务队列。

遇到宏任务与微任务混合的面试题,关键不是死记顺序,而是还原事件循环每一步的“现场”:同步代码执行完后,微任务队列必须清空,之后才轮到下一个宏任务——这个规则不变,其余都是推演。
盯住当前宏任务的边界
每个 script 标签、每个 setTimeout/setInterval 回调、每个 事件处理函数 都是一个独立宏任务。题目中只要出现新的 setTimeout、setImmediate(Node.js)、requestAnimationFrame 或 DOM 事件绑定后的触发点,就代表“新宏任务即将入队”。先划出所有宏任务入口,再逐个分析内部同步 + 微任务逻辑。
同步代码优先,微任务紧随其后
在任一宏任务内:
- 所有同步语句(
console.log、变量赋值、函数调用等)按书写顺序立即执行 -
Promise.resolve().then()、async/await中 await 后的代码、MutationObserver回调,全部进入**当前宏任务对应的微任务队列** - 微任务不跨宏任务——上一个宏任务产生的微任务,不会干扰下一个宏任务内部的同步流程
注意 Promise 构造器内的同步执行
new Promise((resolve) => { console.log('A'); resolve(); }) 中的 console.log('A') 是同步执行的,而 .then() 才是微任务。很多题目靠这点制造“错觉”,比如:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
console.log(1);setTimeout(() => console.log(2), 0);new Promise(r => { console.log(3); r(); }).then(() => console.log(4));console.log(5);
输出一定是 1 → 3 → 5 → 4 → 2,因为 console.log(3) 在 Promise 构造器里,属于同步代码,不是微任务。
async/await 别当成黑盒
async 函数本身返回 Promise,await 后的表达式会先求值(同步),然后暂停函数,把后续代码塞进微任务队列。例如:
-
await Promise.resolve()→ 后续代码进微任务 -
await fetch(...)→ 网络请求发出去,但await后的代码仍进微任务(只是要等 Promise settle) - 连续两个
await,第二个 await 的微任务,要等第一个微任务执行完、Promise 再次 resolve 后才入队
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










