搞定 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 输出类题目本质不难,关键是理解执行机制。多刷题、多总结,做到心中有序,你也能在面试中游刃有余。

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

相关推荐
狂炫冰美式6 分钟前
不谈技术,搞点文化 🧀 —— 从复活一句明代残诗破局产品迭代
前端·人工智能·后端
xw51 小时前
npm几个实用命令
前端·npm
!win !1 小时前
npm几个实用命令
前端·npm
代码狂想家1 小时前
使用openEuler从零构建用户管理系统Web应用平台
前端
dorisrv2 小时前
优雅的React表单状态管理
前端
蓝瑟3 小时前
告别重复造轮子!业务组件多场景复用实战指南
前端·javascript·设计模式
dorisrv3 小时前
高性能的懒加载与无限滚动实现
前端
韭菜炒大葱3 小时前
别等了!用 Vue 3 让 AI 边想边说,字字蹦到你脸上
前端·vue.js·aigc
StarkCoder3 小时前
求求你,别在 Swift 协程开头写 guard let self = self 了!
前端
清妍_3 小时前
一文详解 Taro / 小程序 IntersectionObserver 参数
前端