摘要本文系统讲解 JavaScript Promise 核心原理、状态流转、常用 API 及实战场景拆解回调地狱的解决方案手把手实现符合 Promise/A 规范的核心版 Promise结合大量可运行案例覆盖日常开发与高频面试考点帮助开发者彻底掌握异步编程基础摆脱回调嵌套困境。一、前言为什么需要 Promise在 Promise 出现之前JavaScript 异步编程完全依赖回调函数当存在多层异步嵌套时会出现 “回调地狱Callback Hell”代码可读性、维护性极差难以调试。回调地狱痛点示例真实场景javascript运行// 多层异步嵌套获取用户信息 → 获取用户订单 → 获取订单详情 getUserInfo(userId, function(user) { getUserOrder(user.id, function(order) { getOrderDetail(order.id, function(detail) { console.log(detail); // 嵌套3层已混乱嵌套10层直接无法维护 }, function(err) { console.log(err); }); }, function(err) { console.log(err); }); }, function(err) { console.log(err); });Promise 解决的核心问题解决回调地狱实现异步代码扁平化统一异步错误处理避免重复写错误回调支持异步操作串行、并行控制提供标准化的异步编程规范Promise/A 规范二、Promise 核心概念1. 定义Promise 是一个异步操作的容器用于表示一个异步操作的最终完成成功或失败拒绝并返回其结果值。2. 核心特性Promise 有且只有三种状态状态一旦改变无法逆转面试必记pending初始状态异步操作未完成fulfilled成功状态异步操作完成返回结果rejected失败状态异步操作失败返回错误信息状态流转pending → fulfilled或pending → rejected只能二选一支持链式调用then方法彻底摆脱回调嵌套3. 基础语法必背javascript运行// 1. 创建 Promise 实例 const promise new Promise((resolve, reject) { // 异步操作如接口请求、定时器 setTimeout(() { const success true; if (success) { // 成功调用 resolve传入结果 resolve(操作成功返回数据); } else { // 失败调用 reject传入错误信息 reject(new Error(操作失败)); } }, 1000); }); // 2. 调用 then 方法处理成功/失败 promise.then( (res) { console.log(成功, res); // 接收 resolve 传入的值 }, (err) { console.log(失败, err); // 接收 reject 传入的错误 } );三、Promise 常用 API 详解实战必用1. then 方法核心作用注册异步操作的成功 / 失败回调特点返回一个新的 Promise支持链式调用注意then 回调是微任务后续第 44 篇详解javascript运行// 链式调用示例解决回调地狱 new Promise((resolve) { setTimeout(() resolve(1), 1000); }) .then((res) { console.log(res); // 1 return res 1; // 返回值会作为下一个 then 的参数 }) .then((res) { console.log(res); // 2 return new Promise((resolve) resolve(res 1)); // 可返回 Promise }) .then((res) { console.log(res); // 3 });2. catch 方法错误处理作用专门处理 Promise 失败状态替代 then 的第二个参数更规范特点捕获链式调用中所有前面的错误包括 then 中的错误javascript运行new Promise((resolve, reject) { reject(new Error(初始错误)); }) .then((res) { console.log(res); }) .catch((err) { console.log(捕获错误, err.message); // 捕获初始错误 }); // 链式错误传递 new Promise((resolve) resolve(1)) .then((res) { throw new Error(then 中的错误); // 手动抛出错误 }) .then((res) console.log(res)) .catch((err) { console.log(捕获错误, err.message); // 捕获 then 中的错误 });3. finally 方法收尾操作作用无论 Promise 成功还是失败都会执行如关闭加载 loading特点不接收参数不改变 Promise 的状态和结果javascript运行new Promise((resolve, reject) { setTimeout(() resolve(成功), 1000); }) .then((res) console.log(res)) .catch((err) console.log(err)) .finally(() { console.log(无论成功失败都会执行如关闭loading); });4. 静态方法基础Promise.resolve(value)快速创建一个成功状态的 PromisePromise.reject(error)快速创建一个失败状态的 Promisejavascript运行// 快速创建成功 Promise Promise.resolve(100).then((res) console.log(res)); // 100 // 快速创建失败 Promise Promise.reject(new Error(失败)).catch((err) console.log(err));四、Promise 状态流转面试必画1. 状态流转图文字版面试可口述plaintextpending初始 ↗️ ↘️ fulfilled成功 rejected失败 ↓ ↓ then 回调执行 catch 回调执行 ↓ ↓ 返回新 Promise 返回新 Promise2. 关键注意点面试避坑状态一旦改变pending → fulfilled/rejected无法再次改变即使 Promise 已经成功 / 失败再调用 resolve/reject 也无效then/catch/finally 都会返回新的 Promise因此可以链式调用未捕获的 Promise 错误会触发浏览器 Uncaught Error五、手写 Promise核心版面试必写核心思路Promise/A 规范核心定义三种状态pending、fulfilled、rejected接收 executor 函数立即执行传入 resolve、reject 方法resolve 方法将状态改为 fulfilled保存成功结果执行成功回调队列reject 方法将状态改为 rejected保存错误信息执行失败回调队列then 方法注册回调若状态已改变直接执行对应回调手写代码可直接运行面试简化版javascript运行// 手写 Promise符合 Promise/A 核心规范 class MyPromise { // 1. 初始化状态和结果 constructor(executor) { this.status pending; // 初始状态 this.value undefined; // 成功结果 this.reason undefined; // 失败原因 // 2. resolve 方法修改状态为成功保存结果 const resolve (value) { if (this.status pending) { this.status fulfilled; this.value value; } }; // 3. reject 方法修改状态为失败保存错误 const reject (reason) { if (this.status pending) { this.status rejected; this.reason reason; } }; // 4. 执行 executor捕获同步错误 try { executor(resolve, reject); } catch (err) { reject(err); } } // 5. then 方法注册回调 then(onFulfilled, onRejected) { // 成功回调执行 if (this.status fulfilled) { onFulfilled(this.value); } // 失败回调执行 if (this.status rejected) { onRejected(this.reason); } } } // 测试手写 Promise new MyPromise((resolve, reject) { setTimeout(() resolve(手写 Promise 成功), 1000); }).then( (res) console.log(res), (err) console.log(err) );面试加分点补充 “回调队列”处理异步 then 回调可升级为 “完整版手写”说明手写版本无需完全符合 Promise/A 所有细节核心逻辑正确即可六、Promise 实战场景真实项目常用场景 1接口请求封装结合 axiosjavascript运行// 用 Promise 封装接口请求 function request(url, method GET) { return new Promise((resolve, reject) { axios({ url, method }) .then((res) resolve(res.data)) .catch((err) reject(err)); }); } // 使用链式调用无嵌套 request(/api/user) .then((user) request(/api/order?userId${user.id})) .then((order) request(/api/orderDetail?orderId${order.id})) .then((detail) console.log(detail)) .catch((err) console.log(请求错误, err));场景 2异步操作串行执行javascript运行// 需求先获取用户再获取订单再获取详情串行 function getUser() { return Promise.resolve({ id: 1, name: 张三 }); } function getOrder(userId) { return Promise.resolve({ id: 101, userId }); } function getDetail(orderId) { return Promise.resolve({ id: 1001, orderId, goods: 手机 }); } // 串行执行 getUser() .then((user) getOrder(user.id)) .then((order) getDetail(order.id)) .then((detail) console.log(detail)) .catch((err) console.log(err));七、高频面试题必背Promise 有哪三种状态状态可以逆转吗答pending初始、fulfilled成功、rejected失败状态一旦改变无法逆转。Promise.then 为什么能链式调用答then 方法会返回一个新的 Promise因此可以连续调用 then。catch 能捕获哪些错误答捕获前面所有 Promise 的 rejected 状态以及 then 回调中抛出的错误。Promise.resolve 和 new Promise (resolve resolve ()) 有区别吗答基本无区别前者是后者的语法糖更简洁。手写 Promise 的核心要点是什么答定义三种状态、实现 resolve/reject 改变状态、then 方法注册回调。八、总结Promise 是异步编程的标准化解决方案解决回调地狱三种状态不可逆转pending → fulfilled 或 pending → rejectedthen/catch/finally 支持链式调用实现异步操作扁平化手写 Promise 核心状态管理 resolve/reject then 回调注册是后续 async/await、宏任务 / 微任务的基础面试必考