promise的实现

71 阅读2分钟
    /**
     * @params:setup fn
     * 属性:
     * 静态方法:resolve(),reject(),all(),race(),
     * 原型方法:then(),catch(),finaly(),
     */
    class MyPromise {
        // 状态
        static PENDING = "pending";
        static FULFILLED = "fulfilled";
        static REJECTED = "rejected";
        constructor(executor) {
            const { PENDING, FULFILLED, REJECTED } = MyPromise;
            this._state = PENDING;
            this._value = null; // 值或者报错
            this._resolveCallbacks = [];
            this._rejectCallbacks = [];
            try {
                executor(this._resolve.bind(this), this._reject.bind(this));
            } catch (e) {
                this._reject(e);
            }
        }
        // 静态方法
        static resolve(val) {
            // 1.promise return promise;
            /* 2.thenable 
                let thenable = {
                    then: function(resolve, reject) {
                        resolve(42);
                    }
                }
            */
            // 3.其他类型

            if (val instanceof Promise || val instanceof MyPromise) {
                return val;
            }
            if (val && typeof val.then === "function") {
                return new MyPromise(function (resolve, reject) {
                    try {
                        val.then(resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            }
            return new MyPromise(function (resolve, reject) {
                resolve(val);
            });
        }
        static reject(val) {
            return new MyPromise((resolve, reject) => {
                reject(val);
            });
        }
        static all(promiseArr) {
            let count = 0,
                result = [];
            return new MyPromise(function (resolve, reject) {
                promiseArr.forEach((promise, index) => {
                    MyPromise.resolve(promise).then(
                        (res) => {
                            result[index] = res;
                            if (++count == promiseArr.length) {
                                resolve(result);
                                count = 0;
                            }
                        },
                        (err) => {
                            reject(err);
                        }
                    );
                });
            });
        }
        static race(promiseArr) {
            return new MyPromise(function (resolve, reject) {
                promiseArr.forEach((promise) => {
                    MyPromise.resolve(promise).then(
                        (res) => {
                            resolve(res);
                        },
                        (err) => {
                            reject(err);
                        }
                    );
                });
            });
        }
        // 原型方法
        then(onFulfilled, onRejected) {
            onFulfilled =
                typeof onFulfilled == "function" ? onFulfilled : function () {};
            onRejected =
                typeof onRejected == "function" ? onRejected : function () {};
            const { PENDING, FULFILLED, REJECTED } = MyPromise;
            const p = new MyPromise((resolveNext, rejectNext) => {
                const _fulfiledFn = (value) => {
                    try {
                        const result = onFulfilled(value);
                        // 1.promise return promise;
                        /* 2.thenable 
                            let thenable = {
                                then: function(resolve, reject) {
                                    resolve(42);
                                }
                            }
                        */
                        // 3.其他类型
                        if (
                            result instanceof Promise ||
                            result instanceof MyPromise
                        ) {
                            result.then(resolveNext, rejectNext);
                        } else if (
                            result &&
                            typeof result.then === "function"
                        ) {
                            result.then(resolveNext, rejectNext);
                        } else {
                            resolveNext(result);
                        }
                    } catch (err) {
                        rejectNext(err);
                    }
                };
                const _rejectedFn = (reason) => {
                    try {
                        const result = onRejected(reason);
                        // 1.promise return promise;
                        /* 2.thenable 
                            let thenable = {
                                then: function(resolve, reject) {
                                    resolve(42);
                                }
                            }
                        */
                        // 3.其他类型
                        if (
                            result instanceof Promise ||
                            result instanceof MyPromise
                        ) {
                            result.then(resolveNext, rejectNext);
                        } else if (
                            result &&
                            typeof result.then === "function"
                        ) {
                            result.then(resolveNext, rejectNext);
                        } else {
                            resolveNext(result);
                        }
                    } catch (err) {
                        rejectNext(err);
                    }
                };
                switch (this._state) {
                    case PENDING:
                        // 保存回调函数
                        this._resolveCallbacks.push(_fulfiledFn);
                        this._rejectCallbacks.push(_rejectedFn);
                        break;
                    case FULFILLED:
                        _fulfiledFn(this._value);
                        break;
                    case REJECTED:
                        _rejectedFn(this._value);
                        break;
                }
            });
            return p;
        }
        catch(onRejected) {
            return this.then(null, onRejected);
        }
        finaly(callback) {
            this.then(
                (value) => MyPromise.resolve(callback()).then(() => value),
                (err) =>
                    MyPromise.resolve(callback()).then(() => {
                        throw err;
                    })
            );
        }
        // 回调
        _resolve(value) {
            const { PENDING, FULFILLED, REJECTED } = MyPromise;
            // 1.改变状态
            if (this._state !== PENDING) return;

            const _runFulfilledCbs = (val) => {
                this._resolveCallbacks.forEach((onFulfilled) => {
                    onFulfilled(val);
                });
                this._resolveCallbacks.length = 0;
            };
            const _runRejectedCbs = (reason) => {
                this._rejectCallbacks.forEach((onRejected) => {
                    onRejected(reason);
                });
                this._rejectCallbacks.length = 0;
            };
            if (value instanceof MyPromise) {
                // value是promise,当前promise的状态取决于value
                value.then(
                    (val) => {
                        this._state = FULFILLED;
                        this._value = val;
                        _runFulfilledCbs(val);
                    },
                    (reason) => {
                        this._state = REJECTED;
                        this._value = reason;
                        _runRejectedCbs(reason);
                    }
                );
                return;
            }
            // 调用成功回调
            setTimeout(() => {
                // 状态的改变也应该放到下个周期,否则会在当前周期调用then函数的回调
                this._state = FULFILLED;
                this._value = value;
                _runFulfilledCbs(value);
            }, 0);
        }
        _reject(reason) {
            const { PENDING, FULFILLED, REJECTED } = MyPromise;
            if (this.state !== PENDING) {
                return;
            }
            // 调用拒绝回调
            const _runRejectedCbs = (reason) => {
                this._rejectCallbacks.forEach((onRejected) => {
                    onRejected(reason);
                });
                this._rejectCallbacks.length = 0;
            };
            setTimeout(() => {
                this._state = REJECTED;
                this._value = reason;
                _runRejectedCbs(reason);
            }, 0);
        }
    }
    // 测试代码
    // var promise = new MyPromise((resolve, reject) => {
    //     console.log("step-");
    //     setTimeout(() => {
    //         resolve(123);
    //     }, 1000);
    // });

    // promise.then((value) => {
    //     console.log("step--");
    //     console.log("value", value);
    // });

    // console.log("end");
    
    let thenable = {
        then: function (resolve, reject) {
            resolve(42);
        },
    };
    const p2 = MyPromise.resolve(thenable);
    p2.then((val) => {
        console.log(val);
    });