javascript事件循环严格遵循“同步代码→清空微任务→执行一个宏任务”三步交替执行;宏任务含settimeout等,微任务含promise.then等;微任务总在宏任务前执行且会递归清空。

直接看执行流程,不用猜——JavaScript 的宏任务和微任务交替执行,遵循明确的三步循环:同步代码 → 微任务队列清空 → 执行一个宏任务 → 回到微任务队列清空……如此反复。
第一步:识别每行代码归属哪个队列
这是分析的前提。不是所有异步操作都一样:
-
宏任务:
setTimeout、setInterval、setImmediate(Node.js)、I/O 回调、UI 渲染、整个<script></script>标签内容(即全局脚本本身) -
微任务:
Promise.then/catch/finally、async/await后续代码、queueMicrotask()、MutationObserver回调、Node.js 中的process.nextTick()(优先级最高)
注意:setTimeout(fn, 0) 不是“立刻执行”,而是把 fn 推入宏任务队列;而 Promise.resolve().then(fn) 是立刻把 fn 推入微任务队列,哪怕当前还在执行同步代码。
第二步:按事件循环节奏拆解执行流
每次循环只推进一小段,关键节点清晰可数:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 先跑完所有同步代码(包括函数调用、变量赋值、
console.log等),期间遇到宏/微任务就登记进对应队列 - 同步代码一结束,调用栈清空,立即检查微任务队列——只要不为空,就一个个执行,且执行中新增的微任务也会被追加并继续执行,直到彻底清空
- 微任务队列空了,才从宏任务队列取第一个任务执行(注意:只取一个!)
- 这个宏任务执行完后,又回到第二步:再次清空全部微任务,再取下一个宏任务……无限循环
第三步:多层嵌套或连续触发时的处理要点
常见误区是以为“先写的先执行”,其实顺序由队列填充时机和事件循环规则决定:
- 多个
setTimeout比较的是谁先到期,不是谁先写在代码里。例如setTimeout(f1, 0)和setTimeout(f2, 3),即使f2先定义,f1仍大概率先入队、先执行 - 一个宏任务内部产生的微任务(比如
setTimeout回调里调用了Promise.then),会加入当前轮次的微任务队列末尾,但仍在本轮微任务清空阶段执行,不会等到下一轮宏任务之后 -
async/await本质是语法糖,await后面的代码会被包装成Promise.then,属于微任务;而await Promise.resolve()后的语句,会等当前微任务清空后再进入下一步
第四步:用简单日志验证你的判断
别依赖记忆,动手加几行 console.log 就能验证逻辑是否正确:
- 同步输出标为 S
- 微任务输出标为 M
- 宏任务输出标为 A
例如:
console.log('S1');setTimeout(() => console.log('A1'), 0);
Promise.resolve().then(() => console.log('M1'));
console.log('S2');
输出必然是 S1 → S2 → M1 → A1。只要结果不符,说明某处归属判断错了。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










