Promise及其常见API的简单实现

先简单回顾一下Promise

1. Promise构造函数: Promise (excutor) {}
    excutor函数: 同步执行  (resolve, reject) => {}
    resolve函数: 内部定义成功时我们调用的函数 value => {}
    reject函数: 内部定义失败时我们调用的函数 reason => {}
    说明: excutor会在Promise内部立即同步回调,异步操作在执行器中执行

2. Promise.prototype.then方法: (onResolved, onRejected) => {}
    onResolved函数: 成功的回调函数  (value) => {}
    onRejected函数: 失败的回调函数 (reason) => {}
    说明: 指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的promise对象

3. Promise.prototype.catch方法: (onRejected) => {}
    onRejected函数: 失败的回调函数 (reason) => {}
    说明: then()的语法糖, 相当于: then(undefined, onRejected)

	
4. Promise.resolve方法: (value) => {}
    value: 成功的数据或promise对象
    说明: 返回一个成功/失败的promise对象

5. Promise.reject方法: (reason) => {}
    reason: 失败的原因
    说明: 返回一个失败的promise对象

6. Promise.all方法: (promises) => {}
    promises: 包含n个promise的数组
    说明: 返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败

7. Promise.race方法: (promises) => {}
promises: 包含n个promise的数组
说明: 返回一个新的promise, 第一个完成的(最先完成的)promise的结果、状态就是最终的结果、状态
复制代码

步骤

1. 定义整体结构

(function(window) {
    // 定义promise的三种状态
    const PENDING = 'pending';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';

    // 定义Promise构造函数 excutor: 执行器函数(同步执行)
    function Promise(excutor) {
        if(typeof excutor !== 'function') throw new TypeError(`Promise resolver ${excutor} is not a function`);

        // 定义resolve、reject函数
        const resolve = value => { }
        const reject = reason => { }

        try {
            // 立即同步执行excutor函数,将resolve、reject函数作为其参数供之后调用
            excutor(resolve, reject);
        } catch (error) { 
            // 如果excutor函数抛出异常,promise对象变为fulfilled状态
            reject(error);
        }            
    }

    // 定义then方法
    Promise.prototype.then = function (onResolved, onRejected) { }

    // 定义catch方法
    Promise.prototype.catch = function (onRejected) { }        

    // 定义Promise.resolve方法
    Promise.resolve = function (value) { }

    // 定义Promise.reject方法
    Promise.reject = function (reason) { }

    // 定义Promise.all方法
    Promise.all = function (promises) { }

    // 定义Promise.race方法
    Promise.race = function (promises) { }

    //向外暴露Promise构造函数
    window.Promise = Promise;
})(window)
复制代码

2. Promise构造函数的实现

function Promise(excutor) {
    if (typeof excutor !== 'function') throw new TypeError(`Promise resolver ${excutor} is not a function`);

    // 定义promise对象的初始状态、结果以及其状态为PENDING时then方法将来会调用的回调函数集合
    this.PromiseState = PENDING;
    this.PromiseResult = undefined;
    this.callbacks = []; // 存储结构:[{onResolve(){}, onRejectd(){}}]

    const resolve = value => {
        if (this.PromiseState !== PENDING) return; //因为状态只能改变一次,所以要判断一下如果当前状态不是PENDING,如果是则直接结束

        this.PromiseState = FULFILLED; //将状态改为FULFILLED
        this.PromiseResult = value; //保存value数据

        //如果有待执行的callback函数,将其放入微任务队列执行,queueMicrotask是windows下的一个可以发起微任务的函数
        if (this.callbacks.length > 0) {
            queueMicrotask(() => {
                this.callbacks.forEach(callback => {
                    callback.onResolved(value);
                });
            });
        }
    }

    const reject = reason => {
        if (this.PromiseState !== PENDING) return;

        this.PromiseState = REJECTED;
        this.PromiseResult = reason;

        if (this.callbacks.length > 0) {
            queueMicrotask(() => {
                //放入队列中执行所有失败的回调
                this.callbacks.forEach(callback => {
                    callback.onRejected(reason);
                });
            });
        }
    }

    try {
        excutor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}
复制代码

3. then方法的实现

Promise.prototype.then = function (onResolved, onRejected) {
    onResolved = typeof onResolved === 'function' ? onResolved : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {
        throw reason; //向后传递失败的reason,指定默认的失败状态回调(实现错误/异常传透的关键点)
    };

    const _this = this;

    //返回一个新的promise对象,该对象的状态和值由回调函数onResolved()和onRejected()的返回值决定
    return new Promise((resolve, reject) => {
        // 调用指定的回调函数,根据执行结果,改变return的promise的状态和结果
        const handle = callback => {
            /*
            1. 如果回调函数返回值是promise对象,return的promise状态和结果就是这个回调函数返回的promise对象的状态和结果
            2. 如果回调函数返回值不是promise对象,return的promise就会是FULFILLED状态,value就是返回的值
            3. 如果抛出异常,return的promise就会是REJECTED状态,reason是error
            */
            try {
                const result = callback(_this.PromiseResult);
                //如果result为FULFILLED状态则调用resolve方法,反之则调用reject方法
                (result instanceof Promise) ? result.then(resolve, reject) : resolve(result);
            } catch (error) {
                reject(error)
            }
        }

        //如果当前状态是PENDING则把回调函数保存起来,否则放进微任务队列中执行回调函数。
        const options = {
            [PENDING]() {
                _this.callbacks.push({
                    onResolved(value) {
                        handle(onResolved);
                    },
                    onRejected(reason) {
                        handle(onRejected);
                    }
                });
            },
            [FULFILLED]() {
                queueMicrotask(() => handle(onResolved));
            },
            [REJECTED]() {
                queueMicrotask(() => handle(onRejected));
            }
        };
        options[_this.PromiseState]();
    });
}
复制代码

4. catch方法的实现

// catch方法:简化版then方法
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}
复制代码

4. Promise.resolve方法的实现

Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
        // 如果value是promise对象,使用value的状态和结果作为promise的状态结果,否则则返回一个结果是value状态是FULFILLED的promise对象
        (value instanceof Promise) ? value.then(resolve, reject) : resolve(value);
    });
}
复制代码

5. Promise.reject方法的实现

Promise.reject = function (reason) {
    //返回一个状态为RJECTED的promise对象
    return new Promise((resolve, reject) => reject(reason));
}
复制代码

6. Promise.all方法的实现

Promise.all = function (promises) {
    //定义一个用于保存所有状态为FULFILLED的promise对象value的数组以及用于保存FULFILLED状态的promise对象数量的变量
    const values = new Array(promises.length);
    let resolvedCount = 0;

    return new Promise((resolve, reject) => {
        //遍历promise获取每个promise的结果
        promises.forEach((p, index) => {
            //如果数组中的元素不是promise对象,则将其变为成功的promise对象
            Promise.resolve(p).then(
                value => { //p为FULFILLED状态,将其value保存到values中,FULFILLED状态的promise对象数量+1
                    resolvedCount++;
                    /* 
                    注意:
                        不能用values.push(value),因为then()中的回调函数时异步的,所以我们无法确定谁先执行完,
                        结果就是先执行完回调函数的value先添加至数组values中,导致values中value不能与promises数组中的promise对象一一对应。
                    解决方法:
                        values[index] = value;这样不管哪个回调函数先执行完,都会放在对应的位置上。
                    */
                    values[index] = value;
                    /* 
                    如果所有的promise对象都是FULFILLED状态,将return的promise对象状态变为FULFILLED
                    注意:
                        为什么不用values.length === promises.length作为判断条件?
                        这是因为上一步values[index] = value的原因,假如最后一个promise的onResolved()先执行完,则values.length === promises.length,这时会直接执行resolve(values);
                    解决方法:
                        定义一个变量resolvedCount = 0,每执行一次onResolved()就+1
                     */
                    if (resolvedCount === promises.length) resolve(values);
                },
                /* 
                假如有多个REJECTED状态的promise对象,reject(reason);会调用多次吗?前面调用的reject会被覆盖吗?
                    会调用多次,但后面调用的不会将前面覆盖,因为一个promise对象的状态只能更改一次,
                    当调用reject的时候,函数内部会首先判断该promise的对象状态是否为PENDING,如果不是,就则直接return了。
                */
                reject
            )
        })
    });
}
复制代码

7. Promise.race方法的实现

Promise.race = function (promises) {
    //返回一个promise,其结果由第一个完成的promise决定
    return new Promise((resolve, reject) => {
        promises.forEach(p => {
            //如果数组中的元素不是promise对象,则将其变为FULFILLED状态的promise对象
            Promise.resolve(p).then(resolve, reject);
        })
    });
}
复制代码

代码汇总,引入即可运行

(function (window) {
    // 定义promise的三种状态
    const PENDING = 'pending';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';

    // 定义Promise构造函数 excutor: 执行器函数(同步执行)
    function Promise(excutor) {
        if (typeof excutor !== 'function') throw new TypeError(`Promise resolver ${excutor} is not a function`);

        // 定义promise对象的初始状态、结果以及其状态为PENDING时then方法将来会调用的回调函数集合
        this.PromiseState = PENDING;
        this.PromiseResult = undefined;
        this.callbacks = []; // 存储结构:[{onResolve(){}, onRejectd(){}}]

        const resolve = value => {
            if (this.PromiseState !== PENDING) return; //因为状态只能改变一次,所以要判断一下如果当前状态不是PENDING,如果是则直接结束

            this.PromiseState = FULFILLED; //将状态改为FULFILLED 
            this.PromiseResult = value; //保存value数据

            //如果有待执行的callback函数,立即异步执行回调
            if (this.callbacks.length > 0) {
                queueMicrotask(() => {
                    this.callbacks.forEach(callback => {
                        callback.onResolved(value);
                    });
                });
            }
        }

        const reject = reason => {
            if (this.PromiseState !== PENDING) return;

            this.PromiseState = REJECTED;
            this.PromiseResult = reason;

            if (this.callbacks.length > 0) {
                queueMicrotask(() => {
                    //放入队列中执行所有失败的回调
                    this.callbacks.forEach(callback => {
                        callback.onRejected(reason);
                    });
                });
            }
        }

        try {
            excutor(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }

    // 定义then方法
    Promise.prototype.then = function (onResolved, onRejected) {
        onResolved = typeof onResolved === 'function' ? onResolved : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => {
            throw reason; //向后传递失败的reason,指定默认的失败状态回调(实现错误/异常传透的关键点)
        };

        const _this = this;

        //返回一个新的promise对象,该对象的状态和值由回调函数onResolved()和onRejected()的返回值决定
        return new Promise((resolve, reject) => {
            // 调用指定的回调函数,根据执行结果,改变return的promise的状态和结果
            const handle = callback => {
                /*
                1. 如果回调函数返回值是promise对象,return的promise状态和结果就是这个回调函数返回的promise对象的状态和结果
                2. 如果回调函数返回值不是promise对象,return的promise就会是FULFILLED 状态,value就是返回的值
                3. 如果抛出异常,return的promise就会是REJECTED状态,reason是error
                */
                try {
                    const result = callback(_this.PromiseResult);
                    //如果result为FULFILLED 状态则调用resolve方法,反之则调用reject方法
                    (result instanceof Promise) ? result.then(resolve, reject) : resolve(result);
                } catch (error) {
                    reject(error)
                }
            }

            //如果当前状态是PENDING则把回调函数保存起来,否则放进宏任务队列中执行回调函数。
            const options = {
                [PENDING]() {
                    _this.callbacks.push({
                        onResolved(value) {
                            handle(onResolved);
                        },
                        onRejected(reason) {
                            handle(onRejected);
                        }
                    });
                },
                [FULFILLED]() {
                    queueMicrotask(() => handle(onResolved));
                },
                [REJECTED]() {
                    queueMicrotask(() => handle(onRejected));
                }
            };
            options[_this.PromiseState]();
        });
    }

    // 定义catch方法
    Promise.prototype.catch = function (onRejected) {
        return this.then(undefined, onRejected);
    }

    // 定义Promise.resolve方法
    Promise.resolve = function (value) {
        return new Promise((resolve, reject) => {
            // 如果value是promise对象,使用value的状态和结果作为promise的状态结果,否则则返回一个结果是value状态是FULFILLED 的promise对象
            (value instanceof Promise) ? value.then(resolve, reject) : resolve(value);
        });
    }

    // 定义Promise.reject方法
    Promise.reject = function (reason) {
        //返回一个状态为REJECTED的promise对象
        return new Promise((resolve, reject) => reject(reason));
    }

    // 定义Promise.all方法
    Promise.all = function (promises) {
        //定义一个用于保存所有状态为FULFILLED 的promise对象value的数组以及用于保存FULFILLED 状态的promise对象数量的变量
        const values = new Array(promises.length);
        let resolvedCount = 0;

        return new Promise((resolve, reject) => {
            //遍历promise获取每个promise的结果
            promises.forEach((p, index) => {
                //如果数组中的元素不是promise对象,则将其变为成功的promise对象
                Promise.resolve(p).then(
                    value => { //p为FULFILLED 状态,将其value保存到values中,FULFILLED 状态的promise对象数量+1
                        resolvedCount++;
                        /* 
                        注意:
                            不能用values.push(value),因为then()中的回调函数时异步的,所以我们无法确定谁先执行完,
                            结果就是先执行完回调函数的value先添加至数组values中,导致values中value不能与promises数组中的promise对象一一对应。
                        解决方法:
                            values[index] = value;这样不管哪个回调函数先执行完,都会放在对应的位置上。
                        */
                        values[index] = value;
                        /* 
                        如果所有的promise对象都是FULFILLED 状态,将return的promise对象状态变为FULFILLED 
                        注意:
                            为什么不用values.length === promises.length作为判断条件?
                            这是因为上一步values[index] = value的原因,假如最后一个promise的onResolved()先执行完,则values.length === promises.length,这时会直接执行resolve(values);
                        解决方法:
                            定义一个变量resolvedCount = 0,每执行一次onResolved()就+1
                         */
                        if (resolvedCount === promises.length) resolve(values);
                    },
                    /* 
                    假如有多个REJECTED状态的promise对象,reject(reason);会调用多次吗?前面调用的reject会被覆盖吗?
                        会调用多次,但后面调用的不会将前面覆盖,因为一个promise对象的状态只能更改一次,
                        当调用reject的时候,函数内部会首先判断该promise的对象状态是否为PENDING,如果不是,就则直接return了。
                    */
                    reject
                )
            })
        });
    }

    // 定义Promise.race方法
    Promise.race = function (promises) {
        //返回一个promise,其结果由第一个完成的promise决定
        return new Promise((resolve, reject) => {
            promises.forEach(p => {
                //如果数组中的元素不是promise对象,则将其变为FULFILLED 状态的promise对象
                Promise.resolve(p).then(resolve, reject);
            })
        });
    }

    //向外暴露Promise构造函数
    window.Promise = Promise;
})(window)
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享