1. 手写Promise的核心原理与实现
作为一名前端开发者,我经常被问到Promise的实现原理。今天,我将带大家从零开始实现一个完整的Promise类,这不仅是一次编码练习,更是深入理解JavaScript异步编程本质的绝佳机会。
Promise是现代JavaScript异步编程的基石,但很多人只是停留在API使用层面。通过手写实现,你会发现Promise背后的精妙设计:状态机、回调队列、值穿透等机制。我们将从最基础的状态管理开始,逐步实现then方法、链式调用,最后完成静态方法的完整实现。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Promise基础架构设计
2.1 状态机:Promise的核心
Promise本质上是一个状态机,包含三种状态:
- pending:初始状态,表示异步操作尚未完成
- fulfilled:操作成功完成
- rejected:操作失败
状态转换遵循两个重要规则:
- 只能从pending变为fulfilled或rejected,不可逆
- 状态一旦改变,就不能再次改变
这种设计确保了Promise结果的确定性,这也是Promise可靠性的基础。
2.2 构造函数实现
让我们从构造函数开始:
javascript复制class SimplePromise {
constructor(executor) {
this.status = 'pending'; // 初始状态
this.value = undefined; // 成功时的值
this.reason = undefined; // 失败时的原因
// 回调队列,处理异步场景
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === 'pending') {
this.status = 'fulfilled';
this.value = value;
// 异步执行所有成功回调
setTimeout(() => {
this.onFulfilledCallbacks.forEach(fn => fn());
});
}
};
const reject = (reason) => {
if (this.status === 'pending') {
this.status = 'rejected';
this.reason = reason;
// 异步执行所有失败回调
setTimeout(() => {
this.onRejectedCallbacks.forEach(fn => fn());
});
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
}
这里有几个关键设计点:
- 状态检查:通过if条件确保状态只能改变一次
- 回调队列:使用数组存储回调,处理异步resolve/reject的情况
- 异常捕获:用try-catch包裹executor执行,确保同步错误能被捕获
- 异步执行:使用setTimeout确保回调异步执行,符合Promise/A+规范
注意:在实际项目中,setTimeout并不是最优的微任务实现方式,现代JavaScript引擎通常使用更高效的微任务队列。这里为了简化实现,使用setTimeout模拟。
3. then方法的实现与链式调用
3.1 then方法基础实现
then方法是Promise的灵魂,它实现了Promise的链式调用特性:
javascript复制then(onFulfilled, onRejected) {
// 参数可选处理
onFulfilled = typeof onFulfilled === 'function'
? onFulfilled
: value => value;
onRejected = typeof onRejected === 'function'
? onRejected
: reason => { throw reason };
// 返回新的Promise,实现链式调用
return new SimplePromise((resolve, reject) => {
// 处理已完成状态
if (this.status === 'fulfilled') {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolve(x);
} catch (error) {
reject(error);
}
});
}
// 处理已拒绝状态
else if (this.status === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolve(x);
} catch (error) {
reject(error);
}
});
}
// 处理pending状态
e
