一聚教程网:一个值得你收藏的教程网站

热门教程

Promise.then 的异步特性在事件循环中如何体现

时间:2026-06-20 10:43:03 编辑:袖梨 来源:一聚教程网

Promise.then 的回调总在当前同步代码执行完后、下一个宏任务开始前,作为微任务集中执行;无论 Promise 立即或延迟 resolve,.then 回调均入微任务队列,优先级高于宏任务,链式调用和 async/await 均基于此机制。

Promise.then 的异步特性不是“随便晚点执行”,而是严格遵循事件循环中微任务(Microtask)的调度规则:它总在当前同步代码执行完后、下一个宏任务开始前,被集中清空执行。

then 回调一定进微任务队列

无论 Promise 是立即 resolve 还是延迟 resolve,只要调用 .then(),其回调函数就会被放入微任务队列,而不是直接运行。这意味着:

  • 即使 new Promise((resolve) => { resolve(1); }).then(console.log) 中的 Promise 立即完成,console.log 也不会在 new 那一行同步输出;
  • 它会被推迟到本轮事件循环的末尾,在调用栈清空后、但还没取下一个 setTimeout 或 I/O 宏任务之前执行。

微任务优先级高于宏任务

事件循环每轮执行顺序固定:同步代码 → 所有微任务(包括所有 pending 的 then/catch/finally)→ 一个宏任务(如 setTimeout 回调)。例如:

  • console.log('a');
  • Promise.resolve().then(() => console.log('b'));
  • setTimeout(() => console.log('c'), 0);
  • console.log('d');

输出一定是 a → d → b → c。因为 'b' 在微任务队列,'c' 在宏任务队列,后者要等微任务全部跑完才轮到。

链式 then 会生成新微任务

每次 .then() 都返回新 Promise,而这个新 Promise 的状态取决于回调的返回值——无论返回普通值还是另一个 Promise,它的后续 .then() 回调仍会作为新的微任务入队。这保证了链式调用的可预测时序:

  • p.then(x => x * 2).then(y => console.log(y)) 中,第二个 then 的回调不会在第一个回调结束瞬间执行;
  • 它要等第一个回调执行完毕、新 Promise 状态确定后,再作为独立微任务加入队列。

和 async/await 本质一致

async 函数内部的 await 表达式,底层就是基于 Promise.then 实现的。遇到 await promise 时,JS 引擎会把 await 后面的代码包装成 .then 回调,同样塞进微任务队列。所以:

  • async function f() { console.log(1); await Promise.resolve(); console.log(2); } f();
  • 输出 1 → 2,中间的 await 不阻塞主线程,但确保 console.log(2) 是微任务,不是宏任务。

热门栏目