如何手写一个Promise

2021-09-28  本文已影响0人  小豆soybean

参考文章:https://www.jianshu.com/p/23f34c35da0c

const { resolve } = require("path/posix");

class Promise {//Promise里面参数传一个匿名函数,函数的参数是resolve和reject
    // 初始属性设置
    constructor(executor){
        this.promiseState = 'pending';
        this.promiseResult = null;
         // 保存回调函数
        this.callbacks = [];
        
        // resolve都写在constructor里面
        const resolve = (value) => {
            // 判断状态 让Promise只执行一次。
            if (this.promiseState !== 'pending') return;
            this.promiseState = 'fulfilled';
            this.promiseResult = value;
            // 要包到setTimeout里面
            setTimeout(()=> {
                this.callbacks.forEach(cb => cb.onResolved(value));
            })
        }

        const reject = (err) => {
            if (this.callbacks !== 'pending') return;
            this.promiseState = 'rejected';
            this.promiseResult = err;
            setTimeout(()=>{
                this.callbacks.forEach(cb => cb.onRejected(err));
            })
        }
        try {
            executor(resolve, reject);//这里resolve是传递给儿子了, 儿子完成了直接调用就行了。
        } catch (error) {
            reject(error);     
        }
    }
    // then方法
    then(onResolved, onRejected) {
        // 这里处理异常穿透。假如这个then里面啥都没写,下一个then里面写了一个promise还要可以继续执行下去。
        
        if (typeof onResolved != 'function') {
            onResolved = val => val;
        }
        if (typeof onRejected !== 'function') {
            onRejected = error => {throw error;} //随便原样返回就行
        }
        
        // then里面是返回了一个Promise this想要一直穿透就要用箭头函数
        const handleCallback = (callback) => {
            try {
                let res = callback(this.promiseResult);
                if (res instanceof Promise) {
                    // 因为这里是一个promise,处理一下值搞进resolve里面,这样下一个then就能拿到了。
                    res.then(val => resolve(val), error => reject(error));
                } else {
                    resolve(res);
                }
            } catch (error) {
                reject(error);
            }
        }

        //写一个handleCallback函数。
        if (this.promiseState === 'fulfilled') {
            // !!!这里要包一层setTimeout
            setTimeout(()=> {
                handleCallback(onResolved)
            });
        }
        if (this.promiseState === 'rejected') {
            setTimeout(()=> {
                handleCallback(onRejected)
            })
        }
        if (this.promiseState === 'pending') {
            this.callbacks.push({
                onResolved: () => {
                    handleCallback(onResolved)
                },
                onRejected: () => {
                    handleCallback(onRejected)
                }
            })
        }
    }

    catch(onRejected) {
        return this.then(undefined, onRejected);
    }

    // static 方法
    static resolve(value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then( val =>resolve(val), error => reject(error))
            } else {
                resolve(value);
            }
        })
    }

    static rejected(error) {
        // 这里只有reject
        return new Promise((resolve, reject) => {
             reject(error)
        });
    }

    // all方法
    static all(promiseArrays) {
        return new Promise((resolve, reject) => {
            let result = [];
            let length = promiseArrays.length;
            promiseArrays.forEach(promiseObj => {
                promiseObj.then(val => {
                    result.push(val);
                    // 由于是多个异步的关系,所以需要判断是否都执行完毕。
                    if (result.length === length) {
                        resolve(result);
                    }
                }, error => {
                    reject(error)
                })

            })
        })
    }

    // race方法
    static race(promiseArrays) {
        return new Promise((resolve, reject) => {
            promiseArrays.forEach(promiseObj => {
                promiseObj.then((value)=>{
                    resolve(value)
                }, error => {
                    reject(error)
                })
            })

        })
    }

}
上一篇 下一篇

猜你喜欢

热点阅读