搞定 Promise 输出类面试题|以 BFE.dev 五道题为例全面解析

在面试中,经常会遇到一些 考察 JavaScript 异步执行顺序 的 Promise 输出题。这类题目乍一看令人眼花缭乱,但只要掌握了核心知识点,就能轻松搞定。

本文将结合 BFE.dev 上的五道 Promise 面试题,从原理入手,带你逐一拆解,彻底掌握这类题的解法套路。


一、这类面试题到底在考什么?

这些题目主要考察你对 JavaScript 异步执行模型的理解,尤其是以下几点:

  1. 同步任务 vs 异步任务 的执行顺序
  2. 微任务(microtask) vs 宏任务(macrotask)
  3. Promise 的执行流程(executor、then、catch、finally)
  4. then 的参数处理逻辑(如传入非函数)
  5. resolve(promise) 和嵌套 Promise 的行为

掌握这几点,Promise 输出题将不再是难题。


二、题目详解

题目 1:Promise 执行顺序基础题

scss 复制代码
console.log(1)
const promise = new Promise((resolve) => {
  console.log(2)
  resolve()
  console.log(3)
})

console.log(4)

promise.then(() => {
  console.log(5)
}).then(() => {
  console.log(6)
})

console.log(7)

setTimeout(() => {
  console.log(8)
}, 10)

setTimeout(() => {
  console.log(9)
}, 0) 

解题思路:

  • 同步代码立即执行。
  • new Promise() 中的 executor 是同步执行的。
  • then 添加的是 微任务,排在本轮事件循环结束后。
  • setTimeout宏任务,排在下一轮事件循环。

执行顺序:

  1. console.log(1)
  2. 进入 new Promise,输出 23
  3. 输出 4
  4. 注册了两个 then(微任务)
  5. 输出 7
  6. 微任务执行:输出 5,然后 6
  7. 执行 setTimeout 0(宏任务):输出 9
  8. 执行 setTimeout 10:输出 8

输出结果:

复制代码
1
2
3
4
7
5
6
9
8

题目 2:Promise resolve 多次是否生效?

javascript 复制代码
new Promise((resolve, reject) => {
  resolve(1)
  resolve(2)
  reject('error')
}).then((value) => {
  console.log(value)
}, (error) => {
  console.log('error')
}) 

解题思路:

  • Promise 状态一旦确定(resolved/rejected)就不可更改。
  • 只有第一次 resolve(1) 生效。

输出结果:

复制代码
1

题目 3:then 中参数不是函数会怎样?

javascript 复制代码
Promise.resolve(1)
.then(() => 2)
.then(3)
.then((value) => value * 3)
.then(Promise.resolve(4))
.then(console.log) 

解题思路:

  • then(3) 不是函数,相当于 then(undefined),会将上一个值传下去。
  • then(Promise.resolve(4))立即执行 Promise.resolve(4),但它不是函数,不会当作 callback 使用 ,所以和 then(undefined) 效果一样。
  • 整体变为:
javascript 复制代码
Promise.resolve(1)
  .then(() => 2)             // => 2
  .then(undefined)           // => 2
  .then((v) => v * 3)        // => 6
  .then(undefined)           // => 6
  .then(console.log)         // 输出 6

输出结果:

复制代码
6

题目 4:链式 Promise + 异常处理

javascript 复制代码
Promise.resolve(1)
.then((val) => {
  console.log(val)
  return val + 1
}).then((val) => {
  console.log(val)
}).then((val) => {
  console.log(val)
  return Promise.resolve(3)
    .then((val) => {
      console.log(val)
    })
}).then((val) => {
  console.log(val)
  return Promise.reject(4)
}).catch((val) => {
  console.log(val)
}).finally((val) => {
  console.log(val)
  return 10
}).then((val) => {
  console.log(val)
})

解题思路:

  1. 打印 1
  2. 返回 2 → 打印 2
  3. undefined 传给下一个 → 打印 undefined
  4. return Promise.resolve(3).then(...),里面打印 3
  5. 上个 then 没返回值(隐式 undefined)→ 打印 undefined
  6. 抛出 Promise.reject(4) → 进入 catch 打印 4
  7. finally 不会影响值传递,仍是 undefined → 打印 undefined
  8. 打印 undefined

输出结果:

javascript 复制代码
1
2
undefined
3
undefined
4
undefined
undefined

题目 5:resolve(promise) 的行为

javascript 复制代码
const promise = new Promise((resolve, reject) => {
  const promise2 = Promise.reject('error').then(() => {
    console.log(1)
  }, () => {
    console.log(2)
  })
  resolve(promise2)
});
promise.then(console.log);

解题思路:

  • promise2 是一个 rejected Promise,但有 then 捕获了错误并打印 2,并返回一个 fulfilled 的 Promise。
  • 外层 resolve(promise2),会等 promise2 的状态。
  • 所以最终 promise.then(...) 是 resolved 状态,值为 undefined(因为 promise2 的 then 没返回值)

输出结果:

javascript 复制代码
2
undefined

三、总结:拿下 Promise 输出题的 3 个关键点

  1. 掌握事件循环模型:同步任务、微任务、宏任务的执行顺序。

  2. 理解 Promise 的本质:状态不可变、then 传值规则。

  3. 特殊情况要牢记

    • then(非函数) 会被忽略,直接传值。
    • resolve(promise) 会等待内部状态。
    • finally() 不影响链的值传递。

结语

Promise 输出类题目本质不难,关键是理解执行机制。多刷题、多总结,做到心中有序,你也能在面试中游刃有余。

如果你觉得本文有帮助,欢迎点赞收藏关注。

相关推荐
中微子5 分钟前
JavaScript 事件与 React 合成事件完全指南:从入门到精通
前端
Hexene...14 分钟前
【前端Vue】如何实现echarts图表根据父元素宽度自适应大小
前端·vue.js·echarts
爱莉希雅&&&36 分钟前
技术面试题,HR面试题
开发语言·学习·面试
天天扭码1 小时前
《很全面的前端面试题》——HTML篇
前端·面试·html
xw51 小时前
我犯了错,我于是为我的uni-app项目引入环境标志
前端·uni-app
!win !1 小时前
被老板怼后,我为uni-app项目引入环境标志
前端·小程序·uni-app
Burt1 小时前
tsdown vs tsup, 豆包回答一坨屎,还是google AI厉害
前端
群联云防护小杜2 小时前
构建分布式高防架构实现业务零中断
前端·网络·分布式·tcp/ip·安全·游戏·架构
ohMyGod_1233 小时前
React16,17,18,19新特性更新对比
前端·javascript·react.js
前端小趴菜053 小时前
React-forwardRef-useImperativeHandle
前端·vue.js·react.js