Promise执行链由事件循环的微任务机制驱动,.then回调在当前宏任务结束后统一执行,resolve仅改变状态不触发执行,链式调用本质是连续注册微任务。

Promise 执行链不是“自动排队等执行”,而是由事件循环严格调度的微任务机制在驱动。关键不在于 Promise 本身多复杂,而在于你是否清楚 .then 回调何时入队、何时执行、以及它和同步代码、setTimeout 等宏任务之间的真实时序关系。
Promise 构造函数里的代码是同步的
new Promise 传入的 executor 函数会立即执行,里面的同步逻辑(比如 console.log、变量赋值、甚至 resolve() 调用)都属于当前宏任务的一部分。
- resolve() 或 reject() 本身是同步操作,只改变 Promise 状态,不会立刻触发 .then
- 状态变更后,.then 回调并不会马上运行,而是被推入微任务队列,等待当前宏任务结束
- 如果 Promise 已经处于 fulfilled 状态(如 Promise.resolve(1)),后续调用 .then 会立刻把回调加入微任务队列,但仍要等同步栈清空
.then 回调统一走微任务队列
无论 Promise 是立即 resolve 还是延迟 resolve,只要状态已确定,它的 .then/.catch/.finally 回调都会作为微任务注册。它们的执行时机非常明确:
- 所有同步代码执行完毕
- 当前宏任务(比如整个 script 标签、一次 setTimeout 回调)彻底退出
- 引擎立即、依次、全部执行微任务队列中的任务,中途不穿插渲染或宏任务
- 只有微任务队列彻底清空,才会取下一个宏任务(如 setTimeout 回调)
链式调用本质是连续注册微任务
promise.then(fn1).then(fn2) 并不是 fn1 执行完才注册 fn2 —— fn2 的注册发生在 fn1 返回值被处理的那一刻,而这个处理本身也是微任务。
- fn1 执行后若返回普通值,fn2 会在同一轮微任务中被调度(因为 Promise 链会立即用该值 resolve 下一个 Promise)
- fn1 若返回新 Promise,fn2 就要等那个 Promise settle 后,再作为微任务入队
- 这意味着长链可能跨多轮微任务,但每轮都保证“同步 → 微任务 → 宏任务”的节奏不变
别混淆 resolve 和 then 的时机
常见误区是认为 “resolve() 一调,.then 就立刻执行”。实际上:
- resolve() 只负责更新内部状态,并通知所有已注册的 .then 回调准备入队
- 真正决定执行顺序的是 .then 被调用的时刻:它注册回调,但执行权交给微任务队列
- 哪怕写成 Promise.resolve().then(() => {}),这个 .then 也必须等当前同步代码跑完才执行

















