手写 Promise 核心要点总结
1. 三大状态管理
// ✅ 状态应该是私有的,不可外部修改
#state = 'pending'; // pending | fulfilled | rejected
#value = undefined; // 存储成功值或失败原因
#callbacks = []; // 存储等待回调
// ❌ 错误:状态公开可修改
this.state = 'pending'; // 外部可以 p.state = 'xxx'关键点:
- 状态只能从 pending → fulfilled 或 pending → rejected
- 状态一旦改变就不能再变
- 使用私有字段或闭包保证封装性
2. 构造函数执行器(Executor)
constructor(executor) {
// ✅ 定义 resolve 和 reject 函数
const resolve = (value) => {
if (this.#state === 'pending') {
this.#state = 'fulfilled';
this.#value = value;
// 执行所有等待的回调
this.#callbacks.forEach(cb => cb.onFulfilled(value));
}
};
const reject = (reason) => {
if (this.#state === 'pending') {
this.#state = 'rejected';
this.#value = reason;
// 执行所有等待的回调
this.#callbacks.forEach(cb => cb.onRejected(reason));
}
};
// ✅ 控制反转:将控制权交给用户
try {
executor(resolve, reject);
} catch (error) {
reject(error); // 同步错误自动捕获
}
}关键点:
- resolve/reject 只能在 pending 状态时生效
- 状态改变后要立即执行所有已存储的回调
- executor 执行时抛出错误要自动 reject
3. Then 方法的完整实现
then(onFulfilled, onRejected) {
// ✅ 1. 值穿透:处理回调不存在的情况
onFulfilled = onFulfilled || (value => value);
onRejected = onRejected || (reason => { throw reason });
// ✅ 2. 返回新的 Promise(实现链式调用)
return new MyPromise((resolve, reject) => {
// ✅ 3. 封装回调处理函数
const handleFulfilled = () => {
try {
const result = onFulfilled(this.#value);
// ✅ 4. 处理返回值为 Promise 的情况
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
};
const handleRejected = () => {
try {
const result = onRejected(this.#value);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
reject(result);
}
} catch (error) {
reject(error);
}
};
// ✅ 5. 根据当前状态决定执行时机
if (this.#state === 'fulfilled') {
handleFulfilled(); // 同步立即执行
} else if (this.#state === 'rejected') {
handleRejected(); // 同步立即执行
} else if (this.#state === 'pending') {
// 异步等待:存储回调
this.#callbacks.push({
onFulfilled: handleFulfilled,
onRejected: handleRejected
});
}
});
}关键点:
- 必须返回新的 Promise,不能返回 this
- 回调执行要用 try-catch 捕获错误
- 回调返回值如果是 Promise 要等待完成
- pending 状态要存储回调到队列
4. 完整代码模板
class MyPromise {
// 私有字段
#state = 'pending';
#value = undefined;
#callbacks = [];
constructor(executor) {
// resolve 函数
const resolve = (value) => {
if (this.#state === 'pending') {
this.#state = 'fulfilled';
this.#value = value;
this.#callbacks.forEach(cb => cb.onFulfilled(value));
}
};
// reject 函数
const reject = (reason) => {
if (this.#state === 'pending') {
this.#state = 'rejected';
this.#value = reason;
this.#callbacks.forEach(cb => cb.onRejected(reason));
}
};
// 执行 executor
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
// 值穿透
onFulfilled = onFulfilled || (value => value);
onRejected = onRejected || (reason => { throw reason });
// 返回新 Promise
return new MyPromise((resolve, reject) => {
const handleFulfilled = () => {
try {
const result = onFulfilled(this.#value);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
};
const handleRejected = () => {
try {
const result = onRejected(this.#value);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
reject(result);
}
} catch (error) {
reject(error);
}
};
// 状态判断
if (this.#state === 'fulfilled') {
handleFulfilled();
} else if (this.#state === 'rejected') {
handleRejected();
} else {
this.#callbacks.push({
onFulfilled: handleFulfilled,
onRejected: handleRejected
});
}
});
}
// 可选:catch 方法
catch(onRejected) {
return this.then(null, onRejected);
}
// 可选:finally 方法
finally(onFinally) {
return this.then(
value => MyPromise.resolve(onFinally()).then(() => value),
reason => MyPromise.resolve(onFinally()).then(() => { throw reason })
);
}
// 静态方法
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value));
}
static reject(reason) {
return new MyPromise((_, reject) => reject(reason));
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let completed = 0;
if (promises.length === 0) {
resolve(results);
return;
}
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
value => {
results[index] = value;
completed++;
if (completed === promises.length) {
resolve(results);
}
},
reject
);
});
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
}5. 测试用例验证
// 测试1:基本功能
const p1 = new MyPromise((resolve) => {
setTimeout(() => resolve('success'), 1000);
});
p1.then(value => console.log(value)); // 1秒后输出: success
// 测试2:链式调用
new MyPromise(resolve => resolve(1))
.then(v => v + 1)
.then(v => v * 2)
.then(v => console.log(v)); // 输出: 4
// 测试3:返回 Promise
new MyPromise(resolve => resolve(1))
.then(v => new MyPromise(resolve => setTimeout(() => resolve(v + 1), 1000)))
.then(v => console.log(v)); // 1秒后输出: 2
// 测试4:错误处理
new MyPromise((_, reject) => reject('error'))
.catch(e => console.log('catch:', e)); // 输出: catch: error
// 测试5:值穿透
new MyPromise(resolve => resolve(100))
.then()
.then()
.then(v => console.log(v)); // 输出: 100
// 测试6:多个 then 等待
const p2 = new MyPromise(resolve => setTimeout(() => resolve('data'), 1000));
p2.then(v => console.log('1:', v));
p2.then(v => console.log('2:', v));
p2.then(v => console.log('3:', v));
// 1秒后同时输出三条6. 常见错误及避免
| 错误 | 正确做法 |
|---|---|
| ❌ 直接修改 this.state | ✅ 使用私有字段 #state |
| ❌ then 返回 this | ✅ 返回新的 Promise 实例 |
| ❌ 直接 resolve(result) | ✅ 判断 result 是否为 Promise |
| ❌ 不处理值穿透 | ✅ 设置默认回调函数 |
| ❌ 不捕获 try-catch | ✅ 所有回调都要 try-catch |
| ❌ pending 时不存储回调 | ✅ 存储到 callbacks 数组 |
| ❌ resolve/reject 不检查状态 | ✅ 只在 pending 时执行 |
7. 记忆口诀
状态私有不能改,pending 只能变一次
构造函数控反转,同步错误要捕获
then 法返回新实例,回调可选值穿透
try-catch 包回调,Promise 返回要等待
pending 状态存队列,fulfilled/rejected 立即行8. 自测清单
- 状态是私有的,外部无法直接修改
- resolve/reject 只能在 pending 时执行
- 状态改变后执行所有存储的回调
- then 返回新的 Promise
- 值穿透:不传回调时值传递
- 回调返回值是 Promise 时要等待
- 回调执行用 try-catch 包裹
- pending 状态时存储回调
- 支持链式调用
- 错误可以冒泡传递