promise 是微任务机制的关键载体,其回调在当前同步代码执行完毕后立即、全部、按顺序执行,优先级高于宏任务如 settimeout。
promise 在事件循环中不是“参与者”,而是微任务机制的关键载体。它不决定事件循环的结构,但直接决定了哪些代码以什么优先级、在什么时候执行。
Promise 的回调属于微任务
当你调用 .then()、.catch() 或 .finally() 时,传入的函数不会立刻执行,也不会等到下一个宏任务(比如 setTimeout)才运行。它们会被放入微任务队列(Microtask Queue),并在当前同步代码执行完毕、执行栈清空后,立即、全部、按顺序执行。
例如:
console.log('1');
Promise.resolve().then(() => console.log('2'));
setTimeout(() => console.log('3'), 0);
console.log('4');
// 输出顺序:1 → 4 → 2 → 3
这里 '2' 比 '3' 先输出,正是因为 Promise.then 的回调是微任务,而 setTimeout 是宏任务。
微任务队列在每次事件循环中只清空一次
事件循环每轮只取一个宏任务(如主线程脚本、setTimeout 回调),执行完后——
- 立即检查并清空整个微任务队列(所有已排队的
Promise.then、queueMicrotask等); - 不会中途插入新的宏任务,哪怕过程中又创建了新 Promise;
- 清空后才进入渲染(浏览器)或下一个宏任务。
这意味着:
- 连续链式调用
.then()会生成多个微任务,它们会在同一轮微任务阶段依次执行; - 在
.then()回调里再Promise.resolve().then(...),新微任务仍会加入本轮尚未清空的队列尾部,并在本轮继续执行(不是下一轮)。
Promise 状态变化本身是同步的,但回调是异步的
resolve() 或 reject() 的调用是同步行为,它立刻改变 Promise 内部状态(pending → fulfilled/rejected),但注册的 .then 回调并不会同步触发——而是被调度为微任务。这也是为什么你不能在 resolve() 后立刻读取 .then 的结果,必须等微任务执行。
它和 async/await 的关系本质上一致
async 函数返回 Promise,await 后的代码会被编译成 .then() 链,因此也走微任务路径。所以 await 不会让出线程给其他宏任务,而是让控制权回到事件循环,等微任务处理完再继续。
-
Promise.then是微任务入口之一 -
queueMicrotask是更底层的微任务接口 - MutationObserver 和 Node.js 的
process.nextTick也属同类,但优先级略有差异
Promise 的地位,说到底就是:它是开发者最常用、最可控的微任务触发方式,也是异步逻辑与事件循环精准对齐的桥梁。











