在手写实现 Promise 的 then 方法时,核心思路是通过链式调用实现异步任务的处理和传递。以下是实现 then 方法的主要思路:
1. 理解 then 的作用
then 方法的主要功能是:
- 接收两个参数:
onFulfilled(成功回调)和onRejected(失败回调)。 - 根据
Promise的状态(pending、fulfilled、rejected)执行对应的回调函数。 - 返回一个新的
Promise,以便支持链式调用。
2. 处理异步状态
Promise 的状态是关键。then 方法需要根据当前 Promise 的状态来决定如何执行回调:
- 如果当前
Promise是pending状态,则需要将回调函数存储起来,等待状态改变后再执行。 - 如果当前
Promise是fulfilled或rejected状态,则直接执行对应的回调。
3. 返回新的 Promise
then 方法必须返回一个新的 Promise,以便支持链式调用。这个新的 Promise 的状态取决于回调函数的执行结果:
- 如果回调函数返回一个值(非
Promise),新的Promise应该以这个值为参数被resolve。 - 如果回调函数返回一个
Promise,新的Promise的状态应该与返回的Promise状态一致。 - 如果回调函数抛出错误,新的
Promise应该被reject。
4. 实现逻辑
以下是手写 Promise 中 then 方法的简化逻辑:
class MyPromise {
constructor(executor) {
this.state = 'pending'; // 当前状态
this.value = undefined; // 成功的值
this.reason = undefined; // 失败的原因
this.onFulfilledCallbacks = []; // 存储成功回调
this.onRejectedCallbacks = []; // 存储失败回调
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
// 默认处理回调函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };
// 创建一个新的 Promise 作为返回值
const newPromise = new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
// 异步执行回调,确保符合 Promise/A+ 规范
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(newPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(newPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === 'pending') {
// 如果当前是 pending 状态,存储回调函数
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(newPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(newPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return newPromise;
}
}
function resolvePromise(newPromise, x, resolve, reject) {
// 防止循环引用
if (newPromise === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
if (x && (typeof x === 'object' || typeof x === 'function')) {
// x 是 Promise 或类 Promise 对象
let used = false; // 防止多次调用
try {
const then = x.then;
if (typeof then === 'function') {
then.call(
x,
(y) => {
if (used) return;
used = true;
resolvePromise(newPromise, y, resolve, reject);
},
(r) => {
if (used) return;
used = true;
reject(r);
}
);
} else {
if (used) return;
used = true;
resolve(x);
}
} catch (error) {
if (used) return;
used = true;
reject(error);
}
} else {
resolve(x);
}
}
5. 核心要点
- 状态管理:通过
pending、fulfilled和rejected状态控制执行流程。 - 异步处理:使用
setTimeout确保回调函数异步执行,符合Promise/A+规范。 - 返回新的
Promise:通过resolvePromise函数处理回调函数的返回值,支持链式调用。
通过以上思路,可以实现一个符合 Promise/A+ 规范的 then 方法。