手撕Promise真面目(函数方式 / Class方式 Promise 源码 )七

咱们一起奋斗了这么长时间,终于揭开了 Promise 的真面目,是不是有种感觉:
Promise 源码 乍一听很高深,但仔细耐心的一点一点的层层剥茧,其实也并没有那么难
所以:一件事别在还没开始的时候别让你自己的想象把你打败了~~~【哈嘿】

# 函数方式 Promise 源码

(function(window){
    const PENDING = 'pending'
    const RESOLVED = 'resolved'
    const REJECTED = 'rejected'
    
    /**
     * @func Promise 构造函数
     * @param excutor 执行器函数(同步执行)
     */
    function Promise(excutor){
        const that = this;

        // 给 Promise 对象指定一个 status 属性,初始值为 pending
        this.status = PENDING;
        // 给 Promise 对象指定一个 用于存储结果数据的 data 属性
        this.data = undefined;
        // 每个元素的结构 { onResolved(){}, onRejected(){} }
        this.callbacks = [];

        // 定义一个 成功的 回调
        function resolve(value){
            // 如果当前状态不是 pending , 则直接结束
            if(that.status !== PENDING) return;

            // 1. 将状态改为 resolved
            that.status = RESOLVED;
            // 2. 存储 value 数据
            that.data = value;
            // 3. 如果有待执行的 callbacks 函数,则立即异步执行回调函数
            if(that.callbacks.length > 0){
                setTimeout(()=>{
                    // 放入队列中执行所有成功的回调
                    that.callbacks.forEach(callbacksObj => {
                        callbacksObj.onResolved(value);
                    });
                })
            }
        }

        // 定义一个 失败的 回调
        function reject(reason){
            // 如果当前状态不是 pending , 则直接结束
            if(that.status !== PENDING) return;

            // 1. 将状态改为 rejected
            that.status = REJECTED;
            // 2. 存储 value 数据
            that.data = reason;
            // 3. 如果有待执行的 callbacks 函数,则立即异步执行回调函数
            if(that.callbacks.length > 0){
                setTimeout(()=>{
                    // 放入队列中执行所有失败的回调
                    that.callbacks.forEach(callbacksObj => {
                        callbacksObj.onRejected(reason);
                    });
                })
            }
        }

        // 立即同步执行 excutor
        try{
            excutor(resolve,reject)
        }catch(error){
            // 如果执行器抛出异常,则 Promise 对象变为 rejected 状态
            reject(error);
        }
    }

    /**
     * @func Promise 原型对象中的 then()
     * @param onResoled 成功的回调函数
     * @param onRejected 失败的回调函数
     * @returns  返回一个新的 Promise 对象,结果由 onResolved / onRejected 执行结果决定
     */
    Promise.prototype.then = function(onResolved, onRejected){
        const that = this;

        // 向后传递成功的 value
        onResolved = typeof onResolved === 'function' ? onResolved : value => value
        // 指定默认的失败的回调 ( 实现错误/异常传投的关键点 ),向后传递失败的 reason
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

        /**
         * 返回一个新的 Promise 对象
         * 根据执行的结果,改变 return 的 promise 的状态
         */
        return new Promise((resolve, reject)=>{
            // 调用指定的函数处理
            function handle(callback){
                /**
                 * 分三种情况:
                 * 1. 如果回调函数返回的是 Promise,return 的 Promise 结果就是这个 Promise 的结果
                 * 2. 如果回调函数返回的不是 Promise,return 的 Promise 就会成功,value 就是返回的值
                 * 3. 如果抛出异常,return 的Promise就会失败,reason 就是 error
                 */
                try{
                    // 到回调函数的结果
                    const result = callback(that.data);
                    // 判断 result 的类型 
                    if(result instanceof Promise){
                        // 1. 如果回调函数返回的是 Promise,return 的 Promise 结果就是这个 Promise 的结果
                        // 注意:想要拿到 Promise 的结果只能 .then()
                        // 当 result 成功是,让 return 的 Promise 也成功 (resolve)
                        // 当 result 失败是,让 return 的 Promise 也失败 (reject)

                        // 普通写法
                        // result.then(
                        //     value => resolve(value), 
                        //     reject => reject(reject)
                        // )

                        // 简洁写法
                        result.then(resolve, reject);
                    }else{
                        // 2. 如果回调函数返回的不是 Promise,return 的 Promise 就会成功,value 就是返回的值
                        resolve(result);
                    }
                }catch(error){
                    // 3. 如果抛出异常,return 的Promise就会失败,reason 就是 error
                    reject(error);
                }
            }

            // 处理不同状态的 status
            if(that.status === PENDING ){
                // 如果 status 为 pending,则保存回调函数
                that.callbacks.push({
                    onResolved(){ 
                        handle(onResolved) 
                    }, 
                    onRejected(){ 
                        handle(onRejected) 
                    }
                })
            }else if(that.status === RESOLVED){
                // 如果status 为 resolved,则异步执行 onResolve 并改变 return 的 promise 状态
                setTimeout(()=>{
                    handle(onResolved)
                })
            }else{
                // 如果status 为 rejected,则异步执行 onRejected 并改变 return 的 promise 状态
                setTimeout(()=>{
                    handle(onRejected)
                })
            }
        });  
    }

    /**
     * @func Promise 原型对象中的 catch()
     * @param onRejected 失败的回调函数
     * @returns 返回一个新的 Promise 对象
     */ 
    Promise.prototype.catch = function (onRejected) {
        return this.then(undefined, onRejected)
    }

    /**
     * @func Promise 函数对象的 resolve()
     * @param value 成功的回调函数 
     * @returns 返回一个指定结果 value 的成功的 Promise
     */ 
    Promise.resolve = function (value) {
        // 返回一个成功 / 失败的 Promise
        return new Promise((resolve, reject)=>{
            // 判断 value 的类型
            if(value instanceof Promise){
                // 如果是Promise
                value.then(resolve, reject)
            }else{
                // 如果不是 Promise
                resolve(value)
            }
        })
    }

    /**
     * @func Promise 函数对象的 reject()
     * @param reason 失败的回调函数
     * @returns 返回一个指定结果 reject 的失败的 Promise
     */ 
    Promise.reject = function (reason) {
        // 返回一个失败的 Promise
        return new Promise((undefined,reject)=>{
            reject(reason)
        })
    }

    /**
     * @func Promise 函数对象的 resolveDelay()
     * @param value 成功的回调函数 
     * @param time 指定的延迟时间
     * @returns 返回一个指定结果 value 的成功的 Promise
     */ 
    Promise.resolveDelay = function (value, time) {
        // 返回一个成功 / 失败的 Promise
        return new Promise((resolve, reject)=>{
            setTimeout(()=>{
                // 判断 value 的类型
                if(value instanceof Promise){
                    // 如果是Promise
                    value.then(resolve, reject)
                }else{
                    // 如果不是 Promise
                    resolve(value)
                }
            },time)
        })
    }

    /**
     * @func Promise 函数对象的 rejectDelay()
     * @param reason 失败的回调函数
     * @param time 指定的延迟时间
     * @returns 返回一个指定结果 reject 的失败的 Promise
     */ 
    Promise.rejectDelay  = function (reason, time) {
        // 返回一个失败的 Promise
        return new Promise((undefined,reject)=>{
            setTimeout(()=>{
                reject(reason)
            },time)
        })
    }

    /**
     * @func Promise 函数对象的 all()
     * @param  promises 请求数组
     * @returns 返回一个 Promise
     * @returns 只有 Promise 都成功时才成功,只要有一个失败就失败,并返回失败的 Promise
     */
    Promise.all = function(promises){
        // 用来保存所有成功value的数组
        const values = new Array(promises.length);
        // 用来保存成功Promise的数量
        let resolvedCount = 0;
        // 返回一个新的Promise
        return new Promise((resolve, reject)=>{
            // 遍历 promises 获取每个 Promise 的结果
            promises.forEach((p,index)=>{
                Promise.resolve(p).then(
                    value => {
                        resolvedCount++

                        // 将成功的 value 保存至 values
                        values[index] = value;

                        // 如果全部成功,return 的 Promise 的状态为成功
                        if(resolvedCount == promises.length){
                            resolve(values)
                        }
                    },
                    reason =>{
                        // 只要有一个失败了,return 的 Promise 就是失败
                        reject(reason);
                    }
                )
            })
        })
    }

    /**
     * @func Promise 函数对象的 race()
     * @param  promises 请求数组
     * @returns 返回一个 Promise,其结果由第一个完成的 Promise 决定
     */
    Promise.race = function(promises){
        // 返回一个新的 Promise
        return new Promise((resolve, reject)=>{
            // 遍历 promises 取出每个 Promsie 的结果
            promises.forEach(p => {
                Promise.resolve(p).then(
                    value => {
                        // 一旦有一个成功了, return 的 Promise 就成功
                        resolve(value);
                    },  
                    reason =>{
                        // 一旦有一个失败了, return 的 Promise 就失败
                        reject(reason);
                    }
                )
            })
        })
    }
    
    // 暴露给 window
    window.Promise = Promise;
})(window)

# Class方式 Promise 源码

(function(window){
    const PENDING = 'pending'
    const RESOLVED = 'resolved'
    const REJECTED = 'rejected'
    
    /**
     * @func Promise 构造类
     * @param excutor 执行器函数(同步执行)
     */
    class Promise{
        constructor(excutor){
            const that = this;
            // 给 Promise 对象指定一个 status 属性,初始值为 pending
            this.status = PENDING;
            // 给 Promise 对象指定一个 用于存储结果数据的 data 属性
            this.data = undefined;
            // 每个元素的结构 { onResolved(){}, onRejected(){} }
            this.callbacks = [];

            // 定义一个 成功的 回调
            function resolve(value){
                // 如果当前状态不是 pending , 则直接结束
                if(that.status !== PENDING) return;

                // 1. 将状态改为 resolved
                that.status = RESOLVED;
                // 2. 存储 value 数据
                that.data = value;
                // 3. 如果有待执行的 callbacks 函数,则立即异步执行回调函数
                if(that.callbacks.length > 0){
                    setTimeout(()=>{
                        // 放入队列中执行所有成功的回调
                        that.callbacks.forEach(callbacksObj => {
                            callbacksObj.onResolved(value);
                        });
                    })
                }
            }

            // 定义一个 失败的 回调
            function reject(reason){
                // 如果当前状态不是 pending , 则直接结束
                if(that.status !== PENDING) return;

                // 1. 将状态改为 rejected
                that.status = REJECTED;
                // 2. 存储 value 数据
                that.data = reason;
                // 3. 如果有待执行的 callbacks 函数,则立即异步执行回调函数
                if(that.callbacks.length > 0){
                    setTimeout(()=>{
                        // 放入队列中执行所有失败的回调
                        that.callbacks.forEach(callbacksObj => {
                            callbacksObj.onRejected(reason);
                        });
                    })
                }
            }

            // 立即同步执行 excutor
            try{
                excutor(resolve,reject)
            }catch(error){
                // 如果执行器抛出异常,则 Promise 对象变为 rejected 状态
                reject(error);
            }
        }

        /**
         * @func Promise 原型对象中的 then()
         * @param onResoled 成功的回调函数
         * @param onRejected 失败的回调函数
         * @returns  返回一个新的 Promise 对象,结果由 onResolved / onRejected 执行结果决定
         */
        then (onResolved, onRejected){
            const that = this;

            // 向后传递成功的 value
            onResolved = typeof onResolved === 'function' ? onResolved : value => value
            // 指定默认的失败的回调 ( 实现错误/异常传投的关键点 ),向后传递失败的 reason
            onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

            /**
             * 返回一个新的 Promise 对象
             * 根据执行的结果,改变 return 的 promise 的状态
             */
            return new Promise((resolve, reject)=>{
                // 调用指定的函数处理
                function handle(callback){
                    /**
                     * 分三种情况:
                     * 1. 如果回调函数返回的是 Promise,return 的 Promise 结果就是这个 Promise 的结果
                     * 2. 如果回调函数返回的不是 Promise,return 的 Promise 就会成功,value 就是返回的值
                     * 3. 如果抛出异常,return 的Promise就会失败,reason 就是 error
                     */
                    try{
                        // 到回调函数的结果
                        const result = callback(that.data);
                        // 判断 result 的类型 
                        if(result instanceof Promise){
                            // 1. 如果回调函数返回的是 Promise,return 的 Promise 结果就是这个 Promise 的结果
                            // 注意:想要拿到 Promise 的结果只能 .then()
                            // 当 result 成功是,让 return 的 Promise 也成功 (resolve)
                            // 当 result 失败是,让 return 的 Promise 也失败 (reject)

                            // 普通写法
                            // result.then(
                            //     value => resolve(value), 
                            //     reject => reject(reject)
                            // )

                            // 简洁写法
                            result.then(resolve, reject);
                        }else{
                            // 2. 如果回调函数返回的不是 Promise,return 的 Promise 就会成功,value 就是返回的值
                            resolve(result);
                        }
                    }catch(error){
                        // 3. 如果抛出异常,return 的Promise就会失败,reason 就是 error
                        reject(error);
                    }
                }

                // 处理不同状态的 status
                if(that.status === PENDING ){
                    // 如果 status 为 pending,则保存回调函数
                    that.callbacks.push({
                        onResolved(){ 
                            handle(onResolved) 
                        }, 
                        onRejected(){ 
                            handle(onRejected) 
                        }
                    })
                }else if(that.status === RESOLVED){
                    // 如果status 为 resolved,则异步执行 onResolve 并改变 return 的 promise 状态
                    setTimeout(()=>{
                        handle(onResolved)
                    })
                }else{
                    // 如果status 为 rejected,则异步执行 onRejected 并改变 return 的 promise 状态
                    setTimeout(()=>{
                        handle(onRejected)
                    })
                }
            });  
        }

        /**
         * @func Promise 原型对象中的 catch()
         * @param onRejected 失败的回调函数
         * @returns 返回一个新的 Promise 对象
         */ 
        catch (onRejected) {
            return this.then(undefined, onRejected)
        }

        /**
         * @func Promise 函数对象的 resolve()
         * @param value 成功的回调函数 
         * @returns 返回一个指定结果 value 的成功的 Promise
         */ 
        static resolve = function (value) {
            // 返回一个成功 / 失败的 Promise
            return new Promise((resolve, reject)=>{
                // 判断 value 的类型
                if(value instanceof Promise){
                    // 如果是Promise
                    value.then(resolve, reject)
                }else{
                    // 如果不是 Promise
                    resolve(value)
                }
            })
        }

        /**
         * @func Promise 函数对象的 reject()
         * @param reason 失败的回调函数
         * @returns 返回一个指定结果 reject 的失败的 Promise
         */ 
        static reject = function (reason) {
            // 返回一个失败的 Promise
            return new Promise((undefined,reject)=>{
                reject(reason)
            })
        }

        /**
         * @func Promise 函数对象的 resolveDelay()
         * @param value 成功的回调函数 
         * @param time 指定的延迟时间
         * @returns 返回一个指定结果 value 的成功的 Promise
         */ 
        static resolveDelay = function (value, time) {
            // 返回一个成功 / 失败的 Promise
            return new Promise((resolve, reject)=>{
                setTimeout(()=>{
                    // 判断 value 的类型
                    if(value instanceof Promise){
                        // 如果是Promise
                        value.then(resolve, reject)
                    }else{
                        // 如果不是 Promise
                        resolve(value)
                    }
                },time)
            })
        }

        /**
         * @func Promise 函数对象的 rejectDelay()
         * @param reason 失败的回调函数
         * @param time 指定的延迟时间
         * @returns 返回一个指定结果 reject 的失败的 Promise
         */ 
        static rejectDelay  = function (reason, time) {
            // 返回一个失败的 Promise
            return new Promise((undefined,reject)=>{
                setTimeout(()=>{
                    reject(reason)
                },time)
            })
        }

        /**
         * @func Promise 函数对象的 all()
         * @param  promises 请求数组
         * @returns 返回一个 Promise
         * @returns 只有 Promise 都成功时才成功,只要有一个失败就失败,并返回失败的 Promise
         */
        static all = function(promises){
            // 用来保存所有成功value的数组
            const values = new Array(promises.length);
            // 用来保存成功Promise的数量
            let resolvedCount = 0;
            // 返回一个新的Promise
            return new Promise((resolve, reject)=>{
                // 遍历 promises 获取每个 Promise 的结果
                promises.forEach((p,index)=>{
                    Promise.resolve(p).then(
                        value => {
                            resolvedCount++

                            // 将成功的 value 保存至 values
                            values[index] = value;

                            // 如果全部成功,return 的 Promise 的状态为成功
                            if(resolvedCount == promises.length){
                                resolve(values)
                            }
                        },
                        reason =>{
                            // 只要有一个失败了,return 的 Promise 就是失败
                            reject(reason);
                        }
                    )
                })
            })
        }

        /**
         * @func Promise 函数对象的 race()
         * @param  promises 请求数组
         * @returns 返回一个 Promise,其结果由第一个完成的 Promise 决定
         */
        static race = function(promises){
            // 返回一个新的 Promise
            return new Promise((resolve, reject)=>{
                // 遍历 promises 取出每个 Promsie 的结果
                promises.forEach(p => {
                    Promise.resolve(p).then(
                        value => {
                            // 一旦有一个成功了, return 的 Promise 就成功
                            resolve(value);
                        },  
                        reason =>{
                            // 一旦有一个失败了, return 的 Promise 就失败
                            reject(reason);
                        }
                    )
                })
            })
        }
    }
 
    // 暴露给 window
    window.Promise = Promise;
})(window)

下一篇:初探 async 函数 与 awate 表达式

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,928评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,748评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,282评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,065评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,101评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,855评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,521评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,414评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,931评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,053评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,191评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,873评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,529评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,074评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,188评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,491评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,173评论 2 357