当前位置: 首页 > news >正文

Promise 高频面试题

文章目录

  • 前言
    • ✅ 一、Promise 基础面试题
      • **1. Promise 是什么?解决了什么问题?**
      • **2. Promise 有哪几种状态?能否变更多次?**
      • **3. 以下代码输出什么?**
    • 🧠 二、进阶 Promise 面试题
      • **4. then 和 catch 的区别?可以多次 then 吗?**
      • **5. 如何实现 Promise 链式调用?**
      • **6. finally 的执行时机?能获取返回值吗?**
    • ⚠️ 三、经典面试陷阱题
      • **7. 连续多次调用 resolve/reject 会怎样?**
      • **8. 手写一个 delay 函数:**
      • **9. 如何用 Promise 实现串行请求?**
    • 🔧 四、手写 Promise 核心(可问架构岗)
      • **10. 实现一个最简单的 Promise**
    • ✅ 五、面试总结高频问法归纳
  • **手写一个完整符合 Promise/A+ 规范的 Promise 实现**
    • ✅ 一、代码结构概览
    • ✅ 二、完整实现代码(含注释)
    • ✅ 三、使用测试示例
    • ✅ 四、重点回顾(面试可用)
  • **逐步拆解这份手写 Promise 实现中各函数的调用流程**,**彻底掌握执行顺序、作用和内部关系**。
    • 🧱 一、构造函数 `constructor(executor)`
      • 作用:
      • 执行流程图:
      • 核心代码段:
    • ⚙️ 二、resolve() 和 reject()
      • 作用:
    • 🔁 三、then(onFulfilled, onRejected)
      • 作用:
      • 核心流程:
    • 🔍 四、核心:\_resolvePromise(promise2, x, resolve, reject)
      • 作用:
      • 关键场景:
    • 🚨 五、catch(onRejected)
      • 本质上是:
    • 🔚 六、finally(callback)
      • 特点:
    • 🧪 七、静态方法 resolve / reject
    • 🧠 总体流程图解(简化逻辑)
    • ✅ 小结一句话(适合记忆与面试):


前言

Promise 高频面试题(含详细解析),涵盖基础概念、常见陷阱、进阶应用与源码机制,适合 Vue/React 前端工程师、Node 开发者、技术负责人面试使用:


✅ 一、Promise 基础面试题

1. Promise 是什么?解决了什么问题?

答:

  • Promise 是一种异步编程解决方案,代表一个未来才会完成或失败的操作结果
  • 它避免了回调地狱(callback hell),使异步代码更可读、可维护。

2. Promise 有哪几种状态?能否变更多次?

答:

状态含义
pending初始状态,未完成
fulfilled已完成,调用 resolve() 切换
rejected已失败,调用 reject() 切换
  • Promise 只能从 pending → fulfilled 或 rejected
  • 状态只能变更一次,之后不可逆。

3. 以下代码输出什么?

const p = new Promise((resolve, reject) => {console.log(1)resolve()console.log(2)
})p.then(() => console.log(3))console.log(4)

答:
输出顺序:

1
2
4
3

解释:

  • Promise 构造器是同步执行的;
  • .then() 是异步的微任务,在主线程执行完后才执行。

🧠 二、进阶 Promise 面试题

4. then 和 catch 的区别?可以多次 then 吗?

答:

  • .then(onFulfilled, onRejected) 可处理成功或失败;
  • .catch().then(undefined, onRejected) 的语法糖;
  • Promise 可多次 .then(),每次返回的是一个新的 Promise

5. 如何实现 Promise 链式调用?

Promise.resolve().then(() => {console.log('A')return 'B'}).then(res => {console.log(res)return Promise.resolve('C')}).then(console.log)

输出:

A
B
C

每个 .then() 会返回一个新的 Promise,return 的值会作为下一个 then 的入参。


6. finally 的执行时机?能获取返回值吗?

Promise.resolve(100).finally(() => {console.log('finally')return 200}).then(res => {console.log('then', res)})

输出:

finally
then 100
  • finally() 不影响值传递,它不能修改链的结果。

⚠️ 三、经典面试陷阱题

7. 连续多次调用 resolve/reject 会怎样?

const p = new Promise((resolve, reject) => {resolve('first')resolve('second')reject('error')
})p.then(console.log).catch(console.error)

输出:

first
  • 只有第一次调用有效,之后的 resolvereject 都被忽略。

8. 手写一个 delay 函数:

function delay(ms) {return new Promise(resolve => setTimeout(resolve, ms))
}delay(1000).then(() => console.log('1 秒后输出'))

9. 如何用 Promise 实现串行请求?

const urls = ['url1', 'url2', 'url3']// 串行执行 fetch
urls.reduce((prev, url) => {return prev.then(() => fetch(url).then(res => res.json()))
}, Promise.resolve())

🔧 四、手写 Promise 核心(可问架构岗)

10. 实现一个最简单的 Promise

class MyPromise {constructor(fn) {this._resolve = nullthis._reject = nullfn(this._resolveCallback.bind(this), this._rejectCallback.bind(this))}_resolveCallback(value) {if (this._resolve) this._resolve(value)}_rejectCallback(err) {if (this._reject) this._reject(err)}then(resolveFn) {this._resolve = resolveFnreturn this}catch(rejectFn) {this._reject = rejectFnreturn this}
}

✅ 五、面试总结高频问法归纳

面试问题推荐回答重点
Promise 的三种状态是什么?能变几次?pending → fulfilled/rejected,只变一次
then 和 catch 的区别?catch 是 then 的语法糖,处理错误
finally 有返回值吗?没有,不能影响链的传递
多次调用 resolve 有效吗?只有第一次有效
微任务与宏任务区别?Promise 属于哪种?Promise 属于微任务,执行顺序在 DOM 之后
手写 delay、链式调用、串行执行?熟练掌握,体现编码能力与思维清晰度

手写一个完整符合 Promise/A+ 规范的 Promise 实现

支持:

  • .then() 链式调用
  • 状态变更不可逆
  • 异步执行(模拟微任务)
  • 支持嵌套 Promise 解析
  • 支持 .catch().finally()

✅ 一、代码结构概览

class MyPromise {// 构造函数constructor(executor) {}// then 方法then(onFulfilled, onRejected) {}// catch 方法catch(onRejected) {}// finally 方法finally(callback) {}// resolve/reject 静态方法static resolve(value) {}static reject(reason) {}// 内部私有工具_resolvePromise(promise, x, resolve, reject) {}
}

✅ 二、完整实现代码(含注释)

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class MyPromise {constructor(executor) {this.status = PENDINGthis.value = undefinedthis.reason = undefinedthis.onFulfilledCallbacks = []this.onRejectedCallbacks = []const resolve = value => {if (this.status === PENDING) {this.status = FULFILLEDthis.value = value// 执行成功回调队列this.onFulfilledCallbacks.forEach(fn => fn())}}const reject = reason => {if (this.status === PENDING) {this.status = REJECTEDthis.reason = reason// 执行失败回调队列this.onRejectedCallbacks.forEach(fn => fn())}}try {executor(resolve, reject)} catch (err) {reject(err)}}then(onFulfilled, onRejected) {// 值穿透处理onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => valonRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }const promise2 = new MyPromise((resolve, reject) => {const execCallback = (callback, value, resolve, reject) => {queueMicrotask(() => {try {const x = callback(value)this._resolvePromise(promise2, x, resolve, reject)} catch (err) {reject(err)}})}if (this.status === FULFILLED) {execCallback(onFulfilled, this.value, resolve, reject)} else if (this.status === REJECTED) {execCallback(onRejected, this.reason, resolve, reject)} else {this.onFulfilledCallbacks.push(() => {execCallback(onFulfilled, this.value, resolve, reject)})this.onRejectedCallbacks.push(() => {execCallback(onRejected, this.reason, resolve, reject)})}})return promise2}/*** x的可能值* x 是个普通值(原始类型)x 是基于 Promises/A+ 规范 promise 对象x 是基于其他规范的 promise 对象x 就是 promise2 (x 与 promise2 指向同一对象)*/_resolvePromise(promise2, x, resolve, reject) {if (x === promise2) {return reject(new TypeError('循环引用'))}if (x && (typeof x === 'object' || typeof x === 'function')) {let called = falsetry {const then = x.thenif (typeof then === 'function') {then.call(x,y => {if (called) returncalled = truethis._resolvePromise(promise2, y, resolve, reject)},err => {if (called) returncalled = truereject(err)})} else {resolve(x)}} catch (err) {if (!called) reject(err)}} else {resolve(x)}}catch(onRejected) {return this.then(null, onRejected)}finally(callback) {return this.then(value => MyPromise.resolve(callback()).then(() => value),reason => MyPromise.resolve(callback()).then(() => { throw reason }))}static resolve(val) {if (val instanceof MyPromise) return valreturn new MyPromise(resolve => resolve(val))}static reject(reason) {return new MyPromise((_, reject) => reject(reason))}
}

✅ 三、使用测试示例

const p = new MyPromise((resolve, reject) => {setTimeout(() => {resolve('hello')}, 1000)
})p.then(res => {console.log('结果:', res)return '下一步'
}).then(res => {console.log('第二步:', res)
})

✅ 四、重点回顾(面试可用)

功能点实现说明
状态管理PENDINGFULFILLED / REJECTED
回调队列onFulfilledCallbacks / onRejectedCallbacks
异步执行使用 queueMicrotask() 模拟微任务行为
then 链式调用每次返回一个新 Promise,并延续结果
嵌套 Promise 解析_resolvePromise 递归处理
值穿透非函数处理 fallback 行为

逐步拆解这份手写 Promise 实现中各函数的调用流程彻底掌握执行顺序、作用和内部关系


🧱 一、构造函数 constructor(executor)

作用:

  • 初始化状态(PENDING
  • 定义 resolve()reject() 函数
  • 执行用户传入的 executor(resolve, reject)

执行流程图:

new MyPromise((resolve, reject) => {// 同步执行resolve('ok') // 或 reject('err')
})

核心代码段:

this.status = PENDING
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []// 包裹 try-catch 捕获执行器错误
try {executor(resolve, reject)
} catch (err) {reject(err)
}

⚙️ 二、resolve() 和 reject()

作用:

  • 确保状态只变一次;
  • 记录值或错误;
  • 执行回调队列。
const resolve = value => {if (this.status === PENDING) {this.status = FULFILLEDthis.value = valuethis.onFulfilledCallbacks.forEach(fn => fn())}
}
const reject = reason => {if (this.status === PENDING) {this.status = REJECTEDthis.reason = reasonthis.onRejectedCallbacks.forEach(fn => fn())}
}

🔁 三、then(onFulfilled, onRejected)

作用:

  • 注册回调函数;
  • 返回新 Promise(用于链式调用);
  • 保证执行异步化(使用 queueMicrotask());
  • 使用 _resolvePromise() 解析 return 值(支持返回嵌套 Promise)。

核心流程:

then(onFulfilled, onRejected) {const promise2 = new MyPromise((resolve, reject) => {if (当前状态是 fulfilled) {queueMicrotask(() => {try {const x = onFulfilled(this.value)_resolvePromise(promise2, x, resolve, reject)} catch (err) {reject(err)}})}else if (当前是 pending) {this.onFulfilledCallbacks.push(() => {queueMicrotask(...)})}})return promise2
}

🔍 四、核心:_resolvePromise(promise2, x, resolve, reject)

作用:

  • 遵守 Promise/A+ 规范的返回值处理逻辑:

    • 如果 x 是对象或函数,尝试取 x.then
    • 如果 x.then 是函数,递归调用
    • 如果不是,就 resolve(x)
    • 避免循环引用

关键场景:

if (x === promise2) {reject(new TypeError('循环引用'))
}if (typeof x === 'object' || typeof x === 'function') {const then = x.thenif (typeof then === 'function') {then.call(x, y => {_resolvePromise(promise2, y, resolve, reject)}, reject)} else {resolve(x)}
}

🚨 五、catch(onRejected)

本质上是:

promise.catch(fn) === promise.then(null, fn)
catch(onRejected) {return this.then(undefined, onRejected)
}

🔚 六、finally(callback)

特点:

  • 无论 resolve 还是 reject 都会执行
  • 不会影响后续链上的值
finally(cb) {return this.then(val => MyPromise.resolve(cb()).then(() => val),err => MyPromise.resolve(cb()).then(() => { throw err }))
}

🧪 七、静态方法 resolve / reject

static resolve(value) {if (value instanceof MyPromise) return valuereturn new MyPromise(resolve => resolve(value))
}static reject(reason) {return new MyPromise((_, reject) => reject(reason))
}

🧠 总体流程图解(简化逻辑)

User -> new MyPromise(executor)-> 构造函数立即执行,注册 resolve/rejectPromise.then(onFulfilled)-> 注册微任务,返回 promise2executor 中 resolve() 调用-> 状态变更 + 执行回调 -> queueMicrotask(onFulfilled)onFulfilled 返回值通过 _resolvePromise 解析-> 支持值 / Promise / thenable 递归处理

✅ 小结一句话(适合记忆与面试):

MyPromise 的核心是状态控制 + 回调队列 + 微任务调度 + 嵌套 Promise 解析,整个 then 链通过递归 _resolvePromise 串联,遵守 A+ 规范、保证异步、可链式。


扩展:
浅显易懂的实现Promise之resolvePromise篇,Promise大收官

http://www.xdnf.cn/news/325171.html

相关文章:

  • 证件阅读机在景区实名制应用场景的方案
  • 【数据库原理及安全实验】实验六 角色访问控制
  • 探索 C++ 语言标准演进:从 C++23 到 C++26 的飞跃
  • 轨迹预测笔记
  • 爽提“双核引擎”:驱动校园餐饮焕新升级
  • 直播数据大屏是什么?企业应如何构建直播数据大屏?
  • cursor配置mcp并使用
  • 2025-05-07-关于API Key 的安全管理办法
  • vue3+vite项目引入tailwindcss
  • ntdll!LdrpNameToOrdinal函数分析之二分查找
  • 数据可视化:php+echarts实现数据可视化
  • MySQL 中常见的日志
  • 《深度学习入门 基于Python的理论实现》思维导图
  • eclipse开发环境中缺少JavaEE组件如何安装
  • Go语言基础学习详细笔记
  • 数据实验分析
  • Transformer自学笔记
  • HarmonyOS 鸿蒙操作物联网设备蓝牙模块、扫描蓝牙、连接蓝牙和蓝牙通信
  • 如何查看电脑显卡配置参数 一文读懂
  • Python----神经网络(《Going deeper with convolutions》论文解读和GoogLeNet网络)
  • 第十二节:图像处理基础-图像平滑处理 (均值滤波、高斯滤波、中值滤波)
  • CTK的插件框架和QTUI集成方法
  • 回溯进阶(二):以解数独来深入了解映射
  • SpringBoot应急物资供应管理系统开发设计
  • 可视化图解算法34:二叉搜索树的最近公共祖先
  • 【算法】随机快速排序和随机选择算法
  • [Token]What Kind of Visual Tokens Do We Need? AAAI2025
  • python学智能算法(十一)|机器学习逻辑回归深入(Logistic回归)
  • skywalking服务安装与启动
  • AbMole的Calcein-AM/PI细胞双染试剂盒,精准区分细胞活死状态