Event Loop、微/宏任务队列理解困惑及代码执行顺序疑问
理解Event Loop与代码执行顺序问题
核心误解点
你之前的预期错误,根源在于Promise构造函数的回调是同步执行的,并非异步任务。很多人会误以为Promise相关代码都是异步,但实际上只有then/catch/finally以及await后续的代码才会进入微任务队列,而Promise构造函数本身是在主线程同步流程里执行的。
代码逐行执行流程(可视化Event Loop)
我们一步步拆解代码的执行顺序,对应Event Loop的各个阶段:
1. 主线程同步执行阶段
- 执行
console.log(1)→ 输出1 - 执行
const wait2sec = new Promise(...):- 立刻执行Promise构造函数内的同步代码:
console.log(2)→ 输出2- 调用
setTimeout(...):将这个回调函数加入宏任务队列(等待2秒后才会被推入执行队列) console.log(4)→ 输出4
- 此时
wait2sec是一个处于pending状态的Promise对象
- 立刻执行Promise构造函数内的同步代码:
- 定义异步函数
X,随后调用X():- 进入
X函数,执行到await wait2sec:- 由于
wait2sec当前是pending状态,引擎会将X函数中await之后的代码(console.log('ok'))注册为wait2sec的then回调(属于微任务,但需等待wait2sec变为fulfilled才会进入微任务队列) - 暂停
X函数的执行,主线程跳出X函数,继续执行后续同步代码
- 由于
- 进入
- 执行
console.log(5)→ 输出5 - 此时主线程的同步代码全部执行完毕,开始处理任务队列
2. 任务队列处理阶段
- 首先检查微任务队列:此时
wait2sec仍为pending,没有可执行的微任务,主线程进入等待状态 - 2秒后,
setTimeout的回调被推入宏任务队列,主线程开始执行这个宏任务:console.log(3)→ 输出3- 调用
resolve(true):将wait2sec的状态改为fulfilled,同时将之前注册的then回调(console.log('ok'))加入微任务队列
- 当前宏任务执行完毕,主线程再次检查微任务队列,发现有可执行任务:
- 执行
console.log('ok')→ 输出ok
- 执行
最终输出顺序验证
按照上述流程,实际输出顺序为:1 → 2 → 4 → 5 → 3 → ok,和你看到的结果一致。
关键知识点总结
- 同步代码:优先在主线程执行,执行完毕后才会处理任务队列
- Promise构造函数:内部的回调是同步执行的,只有
then/catch/finally回调才属于微任务 - 宏任务:包括
setTimeout、setInterval、I/O操作等,执行优先级低于微任务 - 微任务:包括Promise的
then/catch/finally、await后续代码、process.nextTick(Node.js)等,每次宏任务执行完毕后,会先清空所有微任务队列才会执行下一个宏任务
内容的提问来源于stack exchange,提问作者Ahmed Hassan
相关产品推荐
相关产品推荐

