手写实现 Promise 的 then 方法

142 阅读2分钟

在手写实现 Promisethen 方法时,核心思路是通过链式调用实现异步任务的处理和传递。以下是实现 then 方法的主要思路:


1. 理解 then 的作用

then 方法的主要功能是:

  • 接收两个参数:onFulfilled(成功回调)和 onRejected(失败回调)。
  • 根据 Promise 的状态(pendingfulfilledrejected)执行对应的回调函数。
  • 返回一个新的 Promise,以便支持链式调用。

2. 处理异步状态

Promise 的状态是关键。then 方法需要根据当前 Promise 的状态来决定如何执行回调:

  • 如果当前 Promisepending 状态,则需要将回调函数存储起来,等待状态改变后再执行。
  • 如果当前 Promisefulfilledrejected 状态,则直接执行对应的回调。

3. 返回新的 Promise

then 方法必须返回一个新的 Promise,以便支持链式调用。这个新的 Promise 的状态取决于回调函数的执行结果:

  • 如果回调函数返回一个值(非 Promise),新的 Promise 应该以这个值为参数被 resolve
  • 如果回调函数返回一个 Promise,新的 Promise 的状态应该与返回的 Promise 状态一致。
  • 如果回调函数抛出错误,新的 Promise 应该被 reject

4. 实现逻辑

以下是手写 Promisethen 方法的简化逻辑:

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. 核心要点

  • 状态管理:通过 pendingfulfilledrejected 状态控制执行流程。
  • 异步处理:使用 setTimeout 确保回调函数异步执行,符合 Promise/A+ 规范。
  • 返回新的 Promise:通过 resolvePromise 函数处理回调函数的返回值,支持链式调用。

通过以上思路,可以实现一个符合 Promise/A+ 规范的 then 方法。