JavaScript事件循环中同步任务优先执行,随后清空微任务队列,最后执行下一个宏任务;因此console.log(1);setTimeout(() => console.log(2), 0);Promise.resolve().then(() => console.log(3));console.log(4);输出顺序为1→4→3→2。

JavaScript 的事件循环机制决定了代码中同步任务、异步任务(宏任务和微任务)的执行顺序。理解它,就能准确预测 console.log 的打印顺序。
同步代码优先执行
所有同步语句会按书写顺序立即执行,不等待任何异步操作。这是最基础也最容易忽略的前提。
- 遇到
console.log('A')就立刻打印 - 函数调用、变量赋值、运算等都属于同步行为
- 即使后面跟着
setTimeout或Promise,也不会打断当前同步流程
宏任务与微任务分层排队
异步任务被分为两类:宏任务(macrotask)和微任务(microtask),它们在事件循环中处于不同层级。
- 宏任务包括:
setTimeout、setInterval、setImmediate(Node.js)、I/O、UI 渲染等 - 微任务包括:
Promise.then/catch/finally、queueMicrotask、MutationObserver - 每次宏任务执行完后,会清空当前所有微任务队列,再取下一个宏任务
事件循环每轮只处理一个宏任务
浏览器或 Node.js 运行时每次从宏任务队列中取出一个任务执行,执行完毕后立即检查并执行所有已加入的微任务,之后才进入下一轮循环。
立即学习“Java免费学习笔记(深入)”;
- 比如一个
setTimeout回调是宏任务,它执行完后,会把本轮产生的所有Promise回调依次执行 - 微任务不会被“打断”,同一轮中新增的微任务也会在本轮末尾执行(例如在
then中又调用Promise.resolve().then(...)) - 但新产生的宏任务(如另一个
setTimeout)要等到下一轮循环才执行
常见例子的输出逻辑
看这段典型代码:
console.log(1); setTimeout(() => console.log(2), 0); Promise.resolve().then(() => console.log(3)); console.log(4);
输出是 1 → 4 → 3 → 2,因为:
- 1 和 4 是同步代码,立刻执行
-
Promise.then是微任务,排在当前宏任务末尾执行 -
setTimeout是宏任务,要等当前宏任务 + 所有微任务完成后,才在下一轮执行



















