📝 面试真题解析:阅读代码,写出结果(JavaScript异步执行机制)

113 阅读2分钟

初遇困惑

但面对这道题时,就疑惑:"为什么4会在3之后打印? "

初次解题时的错误推导

// 错误预期:0 1 2 4 3 5 6
// 实际结果:0 1 2 3 4 5 6

一、面试真题再现

请写出以下代码的打印顺序:

Promise.resolve()
  .then(() => {
    console.log(0)
    return Promise.resolve(4)
  })
  .then((res) => {
    console.log(res)
  })

Promise.resolve()
  .then(() => {
    console.log(1)
  })
  .then(() => {
    console.log(2)
  })
  .then(() => {
    console.log(3)
  })
  .then(() => {
    console.log(5)
  })
  .then(() => {
    console.log(6)
  })

正确答案:0 1 2 3 4 5 6

二、深度执行过程解析

第〇阶段 - 初始化

初始微任务队列:[]

第一阶段 - 同步代码执行

  1. 创建两个已完成的Promise实例
  2. 注册各自的.then回调
微任务队列:
[ 第一个Promise的then1, 第二个Promise的then1 ]

第二轮 - 首轮微任务执行

执行第一个Promise.then1

  • 打印 0
  • 返回 Promise.resolve(4)(产生新的Promise)

执行第二个Promise.then1

  • 打印 1
  • 返回普通值(自动包装为Promise)
微任务队列新增:
第一个链需要等待Promise.resolve(4)解析 → 产生两个隐式微任务
第二个链的then2入队

第三轮 - 次轮微任务执行

执行第二个Promise.then2

  • 打印 2
  • 返回普通值
微任务队列新增:
第二个链的then3入队
第一个链继续等待解析(此时尚未处理)

第四轮 - 关键转折点

执行第二个Promise.then3

  • 打印 3
  • 返回普通值
此时第一个链的Promise.resolve(4)解析完成,触发两个微任务:
1. 处理第一个链的then2回调
2. 继续后续链式调用

第五轮 - 异步结果处理

执行第一个Promise.then2

  • 打印 4

执行第二个Promise.then4

  • 打印 5

最终轮 - 收尾阶段

执行第二个Promise.then5

  • 打印 6

三、核心机制图解

graph TD
    A[同步代码] --> B[微任务队列初始化]
    B --> C[执行第一个then1]
    C --> D[触发Promise解析]
    B --> E[执行第二个then1]
    E --> F[链式入队then2]
    F --> G[执行then2]
    G --> H[链式入队then3]
    H --> I[执行then3]
    I --> J[解析完成触发回调]
    J --> K[执行第一个then2]
    K --> L[执行后续then4]
    L --> M[执行最后then5]

四、关键知识点总结

  1. 双阶段Promise解析
    .then()返回Promise时,会产生两个隐式微任务:

    • 等待Promise状态变更
    • 执行后续回调
  2. 链式调用优先级
    每个.then()都会创建新的微任务,即使返回普通值

  3. 事件循环特性
    同一层级的微任务按入队顺序执行,但嵌套Promise会打破线性顺序

  4. V8引擎优化
    现代浏览器对Promise.resolve的快速路径优化会影响执行细节

五、题目来源声明

本题目源自知名技术面试平台 面试派(mianshipai.com) ,该平台汇集了各大厂最新面试真题,特别感谢其精心整理的优质题库为开发者提供的学习支持。建议读者访问官网获取更多面试资源。