15.promise实现(class)

2020-07-03  本文已影响0人  原来哥哥是万家灯火

对外暴露3个实例方法 then、catch、finally
7个静态方法 resolve、reject、all、race、allSetteled、any、try。
采用宏任务方式实现(setTimeout)
核心难点在 then 方法的实现

export default class MockPromise {
    _state = 'pending';
    _value;
    _callBack = [];

    constructor(fn) {
        let resolve = (value) => {
            this._doResolve('fulfilled', value)
        }
        let reject = (error) => {
            this._doResolve('rejected', error)

        }
        fn(resolve, reject)
    }

    _doResolve(state, value) {
        if (this._state !== 'pending') {
            return
        }

        this._state = state;
        this._value = value;

        setTimeout(() => {
            if (this._state === 'fulfilled') {
                this._callBack.forEach(({onFulfilled}) => {
                    onFulfilled && onFulfilled(this._value)
                })
            }
            if (this._state === 'rejected') {
                this._callBack.forEach(({onRejected}) => {
                    onRejected && onRejected(this._value)
                })
            }
        }, 0)
    }

    then(fulfilledHandler, rejectedHandler) {
        return new MockPromise((resolve, reject) => {
            this._callBack.push({
                onFulfilled: value => {
                    let result = fulfilledHandler ? fulfilledHandler(value) : this._value;
                    if (result instanceof MockPromise) {
                        result.then(
                            newValue => {
                                resolve(newValue)
                            },
                            newError => {
                                reject(newError)
                            })
                    } else {
                        resolve(result)
                    }
                },
                onRejected: error => {
                    let result = rejectedHandler ? rejectedHandler(error) : this._value;
                    if (result instanceof MockPromise) {
                        result.then(
                            newValue => {
                                resolve(newValue)
                            },
                            newError => {
                                reject(newError)
                            })
                    } else {
                        reject(result)
                    }
                }
            })
        })
    }

    catch(rejectedHandler) {
        return this.then(null, rejectedHandler)
    }

    finally(finalHandler) {
        return this.then(
            (value) => {
                finalHandler();
                return value
            },
            (error) => {
                finalHandler();
                return error
            }
        )
    }

    static resolve(value) {
        return new MockPromise(resolve => {
            resolve(value)
        })
    }

    static reject(error) {
        return new MockPromise((resolve, reject) => {
            reject(error)
        })
    }

    static all(arr) {
        return new MockPromise((resolve, reject) => {
            let result = [];
            let i = 0;
            for (let p of arr) {
                let len = arr.length;
                p = p instanceof MockPromise ? p : MockPromise.resolve(p);
                p.then(value => {
                    result[i++] = value;
                    if (result.length === len) {
                        resolve(result)
                    }
                }).catch(error => {
                    reject(error)
                })
            }
        })
    }

    static race(arr) {
        return new MockPromise((resolve, reject) => {
            for (let p of arr) {
                p = p instanceof MockPromise ? p : MockPromise.resolve(p);
                p.then(value => {
                    resolve(value)
                }).catch(error => {
                    reject(error)
                })
            }
        })
    }

    static allSettled(arr) {
        return new MockPromise((resolve, reject) => {
            let result = [];
            let i = 0;
            for (let p of arr) {
                let len = arr.length;
                p = p instanceof MockPromise ? p : MockPromise.resolve(p);
                p.then(value => {
                    result[i++] = {status: 'fulfilled', value: value};
                    if (result.length === len) {
                        resolve(result)
                    }
                }).catch(error => {
                    result[i++] = {status: 'rejected', reason: error};
                    if (result.length === len) {
                        reject(result)
                    }
                })
            }
        })
    }

    static any(arr) {
        return new MockPromise((resolve, reject) => {
            let result = [];
            let i = 0;
            for (let p of arr) {
                let len = arr.length;
                p = p instanceof MockPromise ? p : MockPromise.resolve(p);
                p.then(value => {
                    resolve(value)
                }).catch(error => {
                    result[i++] = new Error(error);
                    if (result.length === len) {
                        reject(result)
                    }
                })
            }
        })
    }

    static try(fn) {
        return new MockPromise( (resolve) => {
            resolve(fn())
        })
    }
}

上一篇下一篇

猜你喜欢

热点阅读