二、基础骨架实现
我们先定义构造函数和基础状态。
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
this.status = PENDING; // 初始状态
this.value = undefined; // 成功的值
this.reason = undefined; // 失败的原因
// 成功回调队列
this.onResolvedCallbacks = [];
// 失败回调队列
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
// 执行所有成功回调
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
// 执行所有失败回调
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
}
三、核心逻辑:then 方法的实现
then 是 Promise 的灵魂。它不仅要处理异步,还要支持链式调用(即返回一个新的 Promise)。
then(onFulfilled, onRejected) {
// 参数透传:确保 .then().then() 这种写法依然生效
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };
// 返回一个新的 Promise,实现链式调用
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 规范要求:onFulfilled 必须在微任务中执行,这里模拟微任务
setTimeout(() => {
try {
let x = onFulfilled(this.value);
// 解析 x,让它符合规范(resolvePromise 方法后面实现)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === PENDING) {
// 状态还是 pending,先存起来
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
}
四、最难的部分:resolvePromise 解析逻辑
规范 2.3 节详细定义了如何处理 onFulfilled 的返回值 x。如果 x 是一个 Promise,我们需要等待 it 完成;如果是普通值,直接 resolve。
function resolvePromise(promise2, x, resolve, reject) {
// 1. 防止循环引用
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 2. 如果 x 是对象或函数(可能是 Promise)
if ((x !== null && typeof x === 'object') || typeof x === 'function') {
let called = false; // 确保 resolve 或 reject 只能调用一次
try {
let then = x.then; // 获取 then 方法
if (typeof then === 'function') {
// 如果有 then,说明 x 是 thenable(Promise-like)
then.call(x, (y) => {
if (called) return;
called = true;
// 递归解析 y,因为 y 可能还是个 Promise
resolvePromise(promise2, y, resolve, reject);
}, (r) => {
if (called) return;
called = true;
reject(r);
});
} else {
// 虽然是对象,但没有 then 方法,直接当作普通值
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
// 3. 普通值直接 resolve
resolve(x);
}
}