编辑代码

class MyPromise {
    constructor(executor) {
        this.status = "pending";
        this.value = 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.value = 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
                : (reason) => {
                    throw reason;
                };

        // 为了实现链式调用,创建一个新的promise
        const promise2 = new MyPromise((resolve, reject) => {
            if (this.status === "fulfilled") {
                setTimeout(() => {
                    try {
                        const x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                }, 0);
            }

            if (this.status === "rejected") {
                setTimeout(() => {
                    try {
                        const x = onRejected(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                }, 0);
            }

            if (this.status === "pending") {
                this.onResolvedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            const x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (error) {
                            reject(error);
                        }
                    }, 0);
                });

                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            const x = onRejected(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (error) {
                            reject(error);
                        }
                    }, 0);
                });
            }
        });

        return promise2;
    }

    static all(promises) {
        return new MyPromise((resolve, reject) => {
            const results = [];
            let count = 0;

            promises.forEach((promise, index) => {
                promise.then(
                    (value) => {
                        results[index] = value;
                        count++;

                        if (count === promises.length) {
                            resolve(results);
                        }
                    },
                    (reason) => {
                        reject(reason);
                    }
                );
            });
        });
    }

    static allSettled(promises) {
        return new MyPromise((resolve) => {
            const results = [];
            let count = 0;

            promises.forEach((promise, index) => {
                promise
                    .then((value) => ({ status: "fulfilled", value }))
                    .catch((reason) => ({ status: "rejected", reason }))
                    .then((result) => {
                        results[index] = result;
                        count++;

                        if (count === promises.length) {
                            resolve(results);
                        }
                    });
            });
        });
    }

    static race(promises) {
        return new MyPromise((resolve, reject) => {
            promises.forEach((promise) => {
                promise.then(resolve, reject);
            });
        });
    }
}

function resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
        return reject(new TypeError("Chaining cycle detected for promise"));
    }

    let called = false; // 防止多次调用

    if (x instanceof MyPromise) {
        // 如果x是一个promise对象
        //
        x.then(
            (y) => {
                if (called) return;
                called = true;
                resolvePromise(promise2, y, resolve, reject);
            },
            (reason) => {
                if (called) return;
                called = true;
                reject(reason);
            }
        );
    } else if (x !== null && (typeof x === "object" || typeof x === "function")) {
        try {
            const then = x.then;

            if (typeof then === "function") {
                then.call(
                    x,
                    (y) => {
                        if (called) return;
                        called = true;
                        resolvePromise(promise2, y, resolve, reject);
                    },
                    (reason) => {
                        if (called) return;
                        called = true;
                        reject(reason);
                    }
                );
            } else {
                resolve(x);
            }
        } catch (error) {
            if (called) return;
            called = true;
            reject(error);
        }
    } else {
        resolve(x);
    }
}

// 测试代码·
new MyPromise((resolve, reject) => {
    console.log("start");
    resolve(100);
})
    .then((res) => {
        console.log(res, "----------res");
        return new MyPromise((resolve, reject) => {
            setTimeout(() => {
                resolve(88888);
            }, 1000);
        });
    })
    .then((data) => {
        console.log("xixiixi");
        console.log(data);
    });

console.log("hahhahah");