前置知识
Promise 有三个状态:pending (等待)、fulfilled (成功)、rejected (失败),状态一旦改变就不可逆;
- 状态只能从 pending -> fulfilled 或 pending -> rejected;
- 每个 Promise 实例都有 then 方法,用于注册成功 / 失败的回调;
- 回调函数会异步执行;
手写 Promise/A+
第一步:实现基础的 Promise 结构(状态 + 结果)
-
实现思路:
- 定义 Promise 类,初始化状态为 pending;
- 构造函数接收一个执行器函数 executor,该函数立即执行;
- 实现 resolve 和 reject 方法,用于改变状态和保存结果;
- 状态一旦改变,不能再修改;
-
代码实现:
// 第一步:基础结构 class MyPromise { // 定义三个静态状态常量 static PENDING = 'pending'; static FULFILLED = 'fulfilled'; static REJECTED = 'rejected'; constructor(executor) { // 初始化状态 this.status = MyPromise.PENDING; // 成功结果 this.value = undefined; // 失败原因 this.reason = undefined; // 成功回调:改变状态 + 保存结果 const resolve = (value) => { // 状态不可逆:只有pending状态才能修改 if (this.status === MyPromise.PENDING) { this.status = MyPromise.FULFILLED; this.value = value; } }; // 失败回调:改变状态 + 保存原因 const reject = (reason) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.REJECTED; this.reason = reason; } }; // 执行器函数立即执行,捕获执行过程中的异常 try { executor(resolve, reject); } catch (error) { reject(error); } } }// 测试1:基础状态和结果 const p1 = new MyPromise((resolve, reject) => { resolve('成功结果'); }); console.log('p1状态:', p1.status); // 输出: fulfilled console.log('p1结果:', p1.value); // 输出: 成功结果 // 测试2:状态不可逆 const p2 = new MyPromise((resolve, reject) => { resolve('第一次resolve'); reject('reject不会生效'); // 状态已改为fulfilled,reject无效 }); console.log('p2状态:', p2.status); // 输出: fulfilled console.log('p2结果:', p2.value); // 输出: 第一次resolve // 测试3:捕获执行器异常 const p3 = new MyPromise((resolve, reject) => { throw new Error('执行器出错了'); }); console.log('p3状态:', p3.status); // 输出: rejected console.log('p3原因:', p3.reason); // 输出: Error: 执行器出错了 -
解析:
- 状态常量:用静态常量定义三个状态,避免魔法字符串,提高代码可读性;
- 构造函数:接收执行器函数 executor,并立即执行;
- resolve/reject:核心逻辑是状态校验,只有 pending 状态才能修改状态,保证状态不可逆;
- 异常捕获:用 try/catch 包裹执行器执行逻辑,执行器内部抛出的异常会直接调用 reject;
第二步:实现 then 方法(基础版)
-
实现思路:
- then 方法接收两个参数:onFulfilled (成功回调)、onRejected (失败回调);
- 根据当前 Promise 状态,执行对应的回调函数;
- 回调函数的参数是 Promise 的 value 或 reason;
-
代码实现:
class MyPromise { // 第一步的代码(省略,保持和上面一致) static PENDING = 'pending'; static FULFILLED = 'fulfilled'; static REJECTED = 'rejected'; constructor(executor) { this.status = MyPromise.PENDING; this.value = undefined; this.reason = undefined; const resolve = (value) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.FULFILLED; this.value = value; } }; const reject = (reason) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.REJECTED; this.reason = reason; } }; try { executor(resolve, reject); } catch (error) { reject(error); } } // 第二步:实现then方法 then(onFulfilled, onRejected) { // 状态为fulfilled,执行成功回调 if (this.status === MyPromise.FULFILLED) { onFulfilled(this.value); } // 状态为rejected,执行失败回调 if (this.status === MyPromise.REJECTED) { onRejected(this.reason); } } }// 测试1:成功状态的then回调 const p1 = new MyPromise((resolve) => { resolve('成功的值'); }).then( (value) => { console.log('成功回调:', value); // 输出: 成功回调: 成功的值 }, (reason) => { console.log('失败回调:', reason); // 不会执行 } ); // 测试2:失败状态的then回调 const p2 = new MyPromise((resolve, reject) => { reject('失败的原因'); }).then( (value) => { console.log('成功回调:', value); // 不会执行 }, (reason) => { console.log('失败回调:', reason); // 输出: 失败回调: 失败的原因 } ); // 测试3:执行器异常触发失败回调 const p3 = new MyPromise(() => { throw new Error('执行器异常'); }).then(null, (reason) => { console.log('捕获异常:', reason.message); // 输出: 捕获异常: 执行器异常 }); -
解析:
- then 方法参数:onFulfilled 是成功时的回调,onRejected 是失败时的回调,参数可选 (这里先不处理不传的情况);
- 状态判断:根据当前 Promise 的状态,执行对应的回调函数,并把 value/reason 作为参数传入;
- 局限性:这个版本的 then 只能处理同步执行器,如果执行器里是异步操作 (比如 setTimeout),then 执行时状态还是 pending,回调不会执行 (第三步解决这个问题);
第三步:支持异步执行器(保存回调队列)
-
实现思路:
- 当 then 执行时状态还是 pending,说明是异步操作,需要把回调函数保存到队列中;
- 当 resolve/reject 执行时,遍历回调队列,执行对应的回调;
- 保证异步操作完成后,回调能被执行;
-
代码实现:
class MyPromise { static PENDING = 'pending'; static FULFILLED = 'fulfilled'; static REJECTED = 'rejected'; constructor(executor) { this.status = MyPromise.PENDING; this.value = undefined; this.reason = undefined; // 新增:保存成功/失败的回调队列(处理异步) this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.FULFILLED; this.value = value; // 新增:状态改变后,执行所有保存的成功回调 this.onFulfilledCallbacks.forEach((callback) => callback(this.value)); } }; const reject = (reason) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.REJECTED; this.reason = reason; // 新增:状态改变后,执行所有保存的失败回调 this.onRejectedCallbacks.forEach((callback) => callback(this.reason)); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { if (this.status === MyPromise.FULFILLED) { onFulfilled(this.value); } if (this.status === MyPromise.REJECTED) { onRejected(this.reason); } // 新增:pending状态时,保存回调到队列 if (this.status === MyPromise.PENDING) { this.onFulfilledCallbacks.push(onFulfilled); this.onRejectedCallbacks.push(onRejected); } } }// 测试1:异步resolve const p1 = new MyPromise((resolve) => { setTimeout(() => { resolve('异步成功的值'); }, 1000); }).then((value) => { console.log('异步成功回调:', value); // 1秒后输出: 异步成功回调: 异步成功的值 }); // 测试2:异步reject const p2 = new MyPromise((resolve, reject) => { setTimeout(() => { reject('异步失败的原因'); }, 1000); }).then(null, (reason) => { console.log('异步失败回调:', reason); // 1秒后输出: 异步失败回调: 异步失败的原因 }); // 测试3:多个then回调(都能执行) const p3 = new MyPromise((resolve) => { setTimeout(() => { resolve('多个回调共享结果'); }, 1000); }); // 第一个then p3.then((value) => { console.log('第一个回调:', value); // 1秒后输出: 第一个回调: 多个回调共享结果 }); // 第二个then p3.then((value) => { console.log('第二个回调:', value); // 1秒后输出: 第二个回调: 多个回调共享结果 }); -
解析:
- 回调队列:新增 onFulfilledCallbacks 和 onRejectedCallbacks 数组,用于保存异步场景下的回调函数;
- pending 处理:当 then 执行时状态还是 pending,说明执行器里是异步操作,把回调函数 push 到对应的队列中;
- 回调执行:当 resolve/reject 被调用时,状态改变,同时遍历回调队列,执行所有保存的回调函数;
- 多 then 支持:一个 Promise 可以调用多次 then,所有回调都会被保存到队列,最终都会执行;
第四步:实现 then 方法的链式调用
-
实现思路:
- then 方法必须返回一个新的 Promise 实例 (核心:链式调用的基础);
- 回调函数的返回值会作为新 Promise 的 resolve 参数;
- 如果回调函数抛出异常,新 Promise 会 reject 这个异常;
- 如果回调返回的是一个 Promise,新 Promise 会等待这个 Promise 完成;
-
代码实现:
class MyPromise { static PENDING = 'pending'; static FULFILLED = 'fulfilled'; static REJECTED = 'rejected'; constructor(executor) { this.status = MyPromise.PENDING; this.value = undefined; this.reason = undefined; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.FULFILLED; this.value = value; this.onFulfilledCallbacks.forEach((callback) => callback()); } }; const reject = (reason) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.REJECTED; this.reason = reason; this.onRejectedCallbacks.forEach((callback) => callback()); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { // 处理回调不传的情况(兼容规范) onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value; onRejected = typeof onRejected === 'function' ? onRejected : (reason) => { throw reason }; // 核心:返回新的Promise,实现链式调用 const newPromise = new MyPromise((resolve, reject) => { // 成功状态处理 if (this.status === MyPromise.FULFILLED) { // 用setTimeout模拟微任务(符合Promise/A+规范) setTimeout(() => { try { // 执行成功回调,获取返回值 const result = onFulfilled(this.value); // 处理返回值,决定新Promise的状态 this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); // 回调抛出异常,新Promise reject } }, 0); } // 失败状态处理 if (this.status === MyPromise.REJECTED) { setTimeout(() => { try { const result = onRejected(this.reason); this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); } // pending状态处理(异步) if (this.status === MyPromise.PENDING) { this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { const result = onFulfilled(this.value); this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const result = onRejected(this.reason); this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); }); } }); return newPromise; } // 新增:处理then回调的返回值(核心工具函数) resolvePromise(newPromise, result, resolve, reject) { // 避免循环引用(自己返回自己) if (newPromise === result) { return reject(new TypeError('Chaining cycle detected for promise #<Promise>')); } // 如果返回值是Promise实例 if (result instanceof MyPromise) { result.then(resolve, reject); } else { // 普通值,直接resolve resolve(result); } } }// 测试1:基础链式调用 new MyPromise((resolve) => { resolve(1); }) .then((value) => { console.log('第一步:', value); // 输出: 第一步: 1 return value + 1; // 返回普通值,作为下一个then的参数 }) .then((value) => { console.log('第二步:', value); // 输出: 第二步: 2 return value + 1; }) .then((value) => { console.log('第三步:', value); // 输出: 第三步: 3 }); // 测试2:返回Promise的链式调用 new MyPromise((resolve) => { resolve(1); }) .then((value) => { // 返回一个新的Promise return new MyPromise((resolve) => { setTimeout(() => { resolve(value + 10); }, 500); }); }) .then((value) => { console.log('异步返回:', value); // 500ms后输出: 异步返回: 11 }); // 测试3:回调抛出异常 new MyPromise((resolve) => { resolve(1); }) .then((value) => { throw new Error('回调出错了'); }) .then( (value) => { console.log('成功回调:', value); // 不会执行 }, (reason) => { console.log('捕获异常:', reason.message); // 输出: 捕获异常: 回调出错了 } ); // 测试4:不传回调的穿透 new MyPromise((resolve) => { resolve('穿透的值'); }) .then() // 不传回调,值会穿透 .then() // 继续穿透 .then((value) => { console.log('穿透结果:', value); // 输出: 穿透结果: 穿透的值 }); // 测试5:循环引用(报错) const p = new MyPromise((resolve) => { resolve(); }); const p2 = p.then(() => { return p2; // 返回自己,循环引用 }); p2.then(null, (reason) => { console.log('循环引用错误:', reason.message); // 输出: Chaining cycle detected for promise #<Promise> }); -
解析:
- 返回新 Promise:then 方法必须返回新的 Promise 实例,这是链式调用的核心 (每个 then 都是一个新的 Promise);
- 微任务模拟:用 setTimeout 模拟 Promise 的微任务执行 (实际 Promise 是微任务,setTimeout 是宏任务,这里简化实现);
- 回调默认值:处理 then 不传回调的情况,成功回调默认返回值本身,失败回调默认抛出异常 (实现值穿透);
- resolvePromise 工具函数:
- 避免循环引用:如果回调返回的 Promise 是当前新创建的 Promise,直接抛出异常;
- 处理 Promise 返回值:如果回调返回 Promise,等待这个 Promise 完成,把它的结果传给新 Promise 的 resolve/reject;
- 处理普通值:直接 resolve 普通值;
- 异常捕获:每个回调执行都用 try/catch 包裹,抛出的异常会让新 Promise 进入 rejected 状态;
第五步:实现 catch 方法(语法糖)
-
实现思路:
- catch 方法是 then(null, onRejected) 的语法糖;
- 直接复用 then 方法的逻辑,简化失败回调的注册;
-
代码实现:
class MyPromise { static PENDING = 'pending'; static FULFILLED = 'fulfilled'; static REJECTED = 'rejected'; constructor(executor) { this.status = MyPromise.PENDING; this.value = undefined; this.reason = undefined; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.FULFILLED; this.value = value; this.onFulfilledCallbacks.forEach((callback) => callback()); } }; const reject = (reason) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.REJECTED; this.reason = reason; this.onRejectedCallbacks.forEach((callback) => callback()); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { // 处理回调不传的情况(兼容规范) onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value; onRejected = typeof onRejected === 'function' ? onRejected : (reason) => { throw reason }; // 核心:返回新的Promise,实现链式调用 const newPromise = new MyPromise((resolve, reject) => { // 成功状态处理 if (this.status === MyPromise.FULFILLED) { // 用setTimeout模拟微任务(符合Promise/A+规范) setTimeout(() => { try { // 执行成功回调,获取返回值 const result = onFulfilled(this.value); // 处理返回值,决定新Promise的状态 this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); // 回调抛出异常,新Promise reject } }, 0); } // 失败状态处理 if (this.status === MyPromise.REJECTED) { setTimeout(() => { try { const result = onRejected(this.reason); this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); } // pending状态处理(异步) if (this.status === MyPromise.PENDING) { this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { const result = onFulfilled(this.value); this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const result = onRejected(this.reason); this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); }); } }); return newPromise; } // 新增:处理then回调的返回值(核心工具函数) resolvePromise(newPromise, result, resolve, reject) { // 避免循环引用(自己返回自己) if (newPromise === result) { return reject(new TypeError('Chaining cycle detected for promise #<Promise>')); } // 如果返回值是Promise实例 if (result instanceof MyPromise) { result.then(resolve, reject); } else { // 普通值,直接resolve resolve(result); } } // 新增:catch方法 catch(onRejected) { return this.then(null, onRejected); } }// 测试1:基础catch使用 new MyPromise((resolve, reject) => { reject('失败原因'); }) .catch((reason) => { console.log('catch捕获:', reason); // 输出: catch捕获: 失败原因 }); // 测试2:链式调用中的catch new MyPromise((resolve) => { resolve(1); }) .then((value) => { throw new Error('链式中的错误'); }) .catch((reason) => { console.log('链式catch:', reason.message); // 输出: 链式catch: 链式中的错误 }); // 测试3:catch后继续链式调用 new MyPromise((resolve, reject) => { reject('初始错误'); }) .catch((reason) => { console.log('处理错误:', reason); // 输出: 处理错误: 初始错误 return '错误已处理'; // 返回值作为下一个then的参数 }) .then((value) => { console.log('处理后的结果:', value); // 输出: 处理后的结果: 错误已处理 }); -
解析:
- 语法糖本质:catch 方法内部直接调用 then(null, onRejected),完全复用 then 方法的逻辑,无需重复编写;
- 链式恢复:catch 方法也返回新的 Promise,所以可以继续链式调用 then,实现 “错误处理后继续执行” 的逻辑;
第六步:实现静态方法(resolve/reject/all)
-
实现思路:
- MyPromise.resolve:快速创建一个已成功的 Promise;
- MyPromise.reject:快速创建一个已失败的 Promise;
- MyPromise.all:接收 Promise 数组,全部成功才成功,有一个失败就失败;
-
代码实现:
class MyPromise { static PENDING = 'pending'; static FULFILLED = 'fulfilled'; static REJECTED = 'rejected'; constructor(executor) { this.status = MyPromise.PENDING; this.value = undefined; this.reason = undefined; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.FULFILLED; this.value = value; this.onFulfilledCallbacks.forEach((callback) => callback()); } }; const reject = (reason) => { if (this.status === MyPromise.PENDING) { this.status = MyPromise.REJECTED; this.reason = reason; this.onRejectedCallbacks.forEach((callback) => callback()); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { // 处理回调不传的情况(兼容规范) onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value; onRejected = typeof onRejected === 'function' ? onRejected : (reason) => { throw reason }; // 核心:返回新的Promise,实现链式调用 const newPromise = new MyPromise((resolve, reject) => { // 成功状态处理 if (this.status === MyPromise.FULFILLED) { // 用setTimeout模拟微任务(符合Promise/A+规范) setTimeout(() => { try { // 执行成功回调,获取返回值 const result = onFulfilled(this.value); // 处理返回值,决定新Promise的状态 this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); // 回调抛出异常,新Promise reject } }, 0); } // 失败状态处理 if (this.status === MyPromise.REJECTED) { setTimeout(() => { try { const result = onRejected(this.reason); this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); } // pending状态处理(异步) if (this.status === MyPromise.PENDING) { this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { const result = onFulfilled(this.value); this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const result = onRejected(this.reason); this.resolvePromise(newPromise, result, resolve, reject); } catch (error) { reject(error); } }, 0); }); } }); return newPromise; } // 新增:处理then回调的返回值(核心工具函数) resolvePromise(newPromise, result, resolve, reject) { // 避免循环引用(自己返回自己) if (newPromise === result) { return reject(new TypeError('Chaining cycle detected for promise #<Promise>')); } // 如果返回值是Promise实例 if (result instanceof MyPromise) { result.then(resolve, reject); } else { // 普通值,直接resolve resolve(result); } } catch(onRejected) { return this.then(null, onRejected); } // 新增:静态resolve方法 static resolve(value) { // 如果value是Promise实例,直接返回 if (value instanceof MyPromise) { return value; } // 否则创建一个已resolve的Promise return new MyPromise((resolve) => { resolve(value); }); } // 新增:静态reject方法 static reject(reason) { return new MyPromise((resolve, reject) => { reject(reason); }); } // 新增:静态all方法 static all(promises) { return new MyPromise((resolve, reject) => { // 校验参数是数组 if (!Array.isArray(promises)) { return reject(new TypeError('The argument must be an array')); } const results = []; // 保存所有成功结果 let completedCount = 0; // 已完成的Promise数量 // 空数组直接resolve if (promises.length === 0) { return resolve(results); } // 遍历处理每个Promise promises.forEach((promise, index) => { // 用resolve包装,确保处理的是Promise(兼容普通值) MyPromise.resolve(promise).then( (value) => { completedCount++; results[index] = value; // 按原数组顺序保存结果 // 所有Promise都完成,resolve结果数组 if (completedCount === promises.length) { resolve(results); } }, (reason) => { // 有一个失败,直接reject reject(reason); } ); }); }); } }// 测试1:MyPromise.resolve MyPromise.resolve(100).then((value) => { console.log('resolve静态方法:', value); // 输出: resolve静态方法: 100 }); // 传入Promise实例 const p = new MyPromise((resolve) => resolve(200)); MyPromise.resolve(p).then((value) => { console.log('resolve传入Promise:', value); // 输出: resolve传入Promise: 200 }); // 测试2:MyPromise.reject MyPromise.reject('静态reject').catch((reason) => { console.log('reject静态方法:', reason); // 输出: reject静态方法: 静态reject }); // 测试3:MyPromise.all 全部成功 const p1 = MyPromise.resolve(1); const p2 = new MyPromise((resolve) => setTimeout(() => resolve(2), 500)); const p3 = 3; // 普通值 MyPromise.all([p1, p2, p3]).then((values) => { console.log('all全部成功:', values); // 500ms后输出: [1, 2, 3] }); // 测试4:MyPromise.all 有失败 const p4 = MyPromise.resolve(1); const p5 = MyPromise.reject('失败了'); MyPromise.all([p4, p5]).catch((reason) => { console.log('all有失败:', reason); // 输出: all有失败: 失败了 }); -
解析:
- static resolve:
- 如果参数是 Promise 实例,直接返回 (避免重复包装);
- 如果是普通值,创建一个新的 Promise 并 resolve 这个值;
- static reject:直接创建一个新的 Promise 并 reject 传入的原因;
- static all:
- 校验参数类型:必须是数组,否则抛出异常;
- 结果顺序:按原数组顺序保存结果 (即使某个 Promise 异步完成);
- 失败快速返回:只要有一个 Promise 失败,立即 reject 这个原因;
- 兼容普通值:用 MyPromise.resolve 包装每个元素,确保能处理普通值;
- static resolve:
总结
-
一步步实现了一个核心功能完整的 Promise,核心关键点回顾:
- 状态管理:Promise 有 pending/fulfilled/rejected 三个状态,状态一旦改变不可逆,这是 Promise 的核心特性;
- then 方法:
- 支持同步 / 异步执行器 (通过回调队列实现);
- 返回新的 Promise 实现链式调用,回调返回值会作为新 Promise 的结果;
- 用 resolvePromise 处理回调返回的 Promise,实现嵌套 Promise 的扁平化;
- 核心扩展:
- catch 是 then(null, onRejected) 的语法糖,简化错误处理;
- 静态方法 (resolve/reject/all) 是常用的语法糖,提升开发效率;
- 所有异步回调都通过异步执行 (模拟微任务),符合 Promise/A+ 规范;
-
这个实现覆盖了 Promise 的核心功能,虽然和浏览器原生 Promise (如微任务、更多静态方法) 还有差距,但足以理解 Promise 的核心原理;
第 4️⃣ 座大山:Promise、Generator、async、await 语法糖
上一篇