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

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

相关推荐
DevUI团队3 分钟前
Electron 入门学习指南:快速搭建跨平台桌面应用
前端·javascript·electron
喝拿铁写前端8 分钟前
路由分析小工具:Vue 2 项目的路由资产一眼掌握
前端
柳鲲鹏14 分钟前
VUE3多国语言切换(国际化)
前端·javascript·vue.js
liangshanbo121514 分钟前
CSS 视觉格式化模型
前端·css
Java知识库27 分钟前
Java基础知识面试题(已整理Java面试宝典pdf版)
java·面试·程序员·编程·面试题
小小小小宇29 分钟前
TypeScript 中 infer 关键字
前端
__不想说话__43 分钟前
面试官问我React状态管理,我召唤了武林群侠传…
前端·react.js·面试
Cutey91644 分钟前
前端SEO优化方案
前端·javascript
webxin6661 小时前
带鱼屏页面该怎么适配?看我的
前端
axinawang1 小时前
SpringBoot整合Java Web三大件
java·前端·spring boot