Promise源码实现2

220 阅读2分钟

上一篇写到了resolvePromise这个方法,这个方法是根据返回不同的x值来进行不同的逻辑处理的。

基本使用

    let p = new Promise(function(resplve,reject){
        resolve()
    })
    
    let p2 = p.then(function(){
        // return p2
        // return 100
        // return new Promise(functionl(resolve,reject){
            resolve(200)
        })
    })
    
    Promise.all([promise1,promise2,100]).then(function(data){
        console.log(data);
    })

resolvePromise实现代码

    function resolvePromise(promise2,x,resolve,reject){
        // 加入返回的x和promise2相等,这样promise2会等待x执行成功或者失败然后才会调用。这样形成了一个自身引用。抛出异常
        if(x===promise2){
            throw new TypeError('TypeError: Chaining cycle detected for promise #<Promise>')
        }
        let called; // 规范要求  一旦成功了 就不能再调用失败
        // x是一个对象或者函数 说明x可能是一个promise
        if(x!=null && type x ==='object' || typeof x === 'function'){
            try{ // 因为当取x.then 的时候可能会抛出异常,所以try捕获一下
                let then = x.then
                if(typeof then ==='function'){
                    // 为什么不直接x.then执行呢? 因为x.then 的时候 不一定哪一次执行的时候会抛出错误
                    then.call(x,function(y){
                        // 因为x执行成功的时候,返回的y可能是原始值、promise、异常,所以这里需要在递归调用一下
                        if(!called){called = true}else{return}
                        resolvePromise(promise2,y,resolve,reject)
                    },function(r){
                        // 错误直接reject
                        if(!called){called = true}else{return}
                        reject(r)
                    })
                }else{ // x为普通值
                    resolve(x)
                }
            }catch(e){
                if(!called){called = true}else{return}
                reject(e)
            }
        }else{
            resolve(x)
        }
    }

Promise.catch

catch方法实际就是then方法成功的回调传递的是null

    Promise.prototype.catch = function(onRejected){
        return this.then(null,onRejected)
    }

Promise.resolve

    Promise.resolve = function(value){
        return new Promise(function(resolve,reject){
            resolve(value)
        })
    }

Promise.reject

    Promise.reject = function(reason){
        return new Promise(function(resolve,reject){
            reject(reason)
        })
    }

Promise.all

    Promise.all = function(promises){
        return new Promise(function(resolve,reject){
            let arr = [];
            let i = 0;
            function processData(index,data){
                arr[index] = data;
                // 这里为什么用一个记数的i,而不是直接用arr.length ===promises.length 判断呢?
                // 因为当执行all方法的时候,如上所述数组里面的100先执行 这时候索引为2 arr的length 已经为3了 直接满足条件判断,而此时其余的promise还没有执行完成。所以需要一个计数器来进行判断
                if(++i === promises.length){
                    resolve(arr)
                }
            }
            for(let i = 0;i<promises.length;i++){
                let promise = promises[i];
                if(typeof promise.then === 'function'){
                    // 当前项为promise
                    promise.then(function(data){
                        processData(i,data);
                    },reject)
                }else{
                    // 非promise 为原始值
                    processData(i,promise)
                }
            }
        })
    }

Promise.race

    Promise.race = function(promises){
        return new Promise(function(resolve,reject){
            for(let i = 0;i<promises.length;i++){
                let promise = promises[i];
                if(typeof promise.then === 'function'){
                   promise.then(resolve,reject)
                }else{
                    resolve(promise)
                }
            }
        })
    }
    

Promise.finally(无论成功还是失败finally里面的方法都会执行)

    Promise.prototype.finally = function(cb){
        return this.then(function(data){
            cb();
            return data
        },function(err){
            cb();
            throw err;
        })
    }

Promise.deferred(相当于promise的语法糖,方便书写)

    Promise.deferred = Promise.defer = function(){
        let dfd = {};
        dfd.promise = new Promise((resolve,reject)=>{
            dfd.resolve = resolve;
            dfd.reject = reject;
        })
        return dfd;
    }
    // 如下使用
    let fs = require('fs')
    function read(url){
        let defer = Promise.defer();
        fs.readFile('./1.txt','utf8',function(err,data){
            if(err) defer.reject(err)
            defer.resolve(data)
        })
        return defer.promise;
    }

Promise的值穿透(就是then可以不传递参数,交到下一个then来处理)

    Promise.prototype.then = function(onFulfilled,onRejected){
        // 处理不传递成功 添加默认值
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(data){return data}
        // 处理不传递失败 添加默认值
        onRejected = typeof onRejected ==='function' ? onRejected : function(err){ throw err}
        
        //.....
    }

Promise测试

可以使用npm库promises-aplus-tests 来进行测试