美文网首页
Promise原理解析

Promise原理解析

作者: williamslau | 来源:发表于2018-03-19 17:42 被阅读0次

    Promise是异步编程的一种解决方案,比回调函数和事件更合理更强大。

    原生的promise用法如下:

    let p=new Promise(function(resolve,reject){
        resolve('成功');
        //reject('失败');
    });
    p.then(function(data){
        console.log(data);
    },function(err){
        console.log(err);
    });
    
    image

    Promise实例中有一个函数,接受两个参数,一个是成功的方法,一个是失败的方法,然后有一个then方法,第一个是成功执行的函数,第二个是失败执行的函数,并且会接收相应的参数。一旦执行成功,就不会再执行失败,反之亦然。

    function Promise(executor){  //executor是一个执行函数
        let self = this;
        self.status = 'pending';
        self.value = undefined; //默认成功的值
        self.reason = undefined; //默认失败的值
        function resolve(value){ //成功状态
            if(self.status === 'pending'){
                self.status = 'resolved';
                self.value = value;
            }
        }
        function reject(reason){  //失败状态
            if(self.status === 'pending'){
                self.status = 'rejected';
                self.reason = reason;
            }
        }
        try{
            executor(resolve,reject);
        }catch(e){      //处理异常状态,传给reject
            reject(e);
        }
    };
    
    Promise.prototype.then = function(onFulfilled,onRejected){
        let self = this;
        if(self.status === 'resolved'){
            onFulfilled(self.value);
        }
        if(self.status === 'rejected'){
            onRejected(self.reason);
        }
    };
    module.exports = Promise;
    

    首先先定义一个Promise函数,并且接受一个executor执行函数,将resolve和reject传参传进去,定义私有属性status,value,reason。
    Promise有三个状态,status用来记录他们:
    初始状态为pending
    成功状态为resolved
    失败状态为rejected

    然后使用prototype挂载一个then方法,
    方法中要传入一个成功的回掉和一个失败的回掉,
    如果成功就调取成功的回掉,
    失败就调取失败的回掉

    最后将函数导出,就实现了一个最基础功能的Promise。

    但是这个Promise还是一个同步的方法,如果想在代码中使用异步,比如:

    let p=new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve('成功');
        },1000);
        //throw new Error('错误');
    });
    

    我们就需要将他变为异步的:

    function Promise(executor){
        let self = this;
        self.status = 'pending';
        self.value = undefined;
        self.reason = undefined;
        self.onResolvedCallbacks= [];  //存放成功的回掉
        self.onRejectedCallbacks= [];  //存放失败的回掉
        function resolve(value){
            if(self.status === 'pending'){
                self.status = 'resolved';
                self.value = value;
                self.onResolvedCallbacks.forEach(function(fn){
                    fn();
                });
            }
        }
        function reject(reason){
            if(self.status === 'pending'){
                self.status = 'rejected';
                self.reason = reason;
                self.onRejectedCallbacks.forEach(function(fn){
                    fn();
                });
            }
        }
        try{
            executor(resolve,reject);
        }catch(e){      //处理异常状态,传给reject
            reject(e);
        }
    }
    
    Promise.prototype.then=function(onFulfilled,onRejected){
        let self = this;
        if(self.status === 'resolved'){
            onFulfilled(self.value);
        }
        if(self.status === 'rejected'){
            onRejected(self.reason);
        }
        if(self.status === 'pending'){
            self.onResolvedCallbacks.push(function(){
                onFulfilled(self.value);
            });
            self.onRejectedCallbacks.push(function(){
                onRejected(self.reason);
            });
        }
    };
    module.exports = Promise;
    

    如果他是异步的,我们就不能在then方法中用status的成功失败状态来判断他走的那,因为then方法执行后有可能params中还没执行resolve或者reject,那么我们就在Promise实例上再新增onResolvedCallbacks和onRejectedCallbacks两个数组来存放他的回掉,如果执行的是成功,失败就会存默认的undefined。在调用时用forEach循环数组依次知性方法。
    原生的Promise还可以then多次:

    function Promise(executor){
        let self = this;
        self.status = 'pending';
        self.value = undefined;
        self.reason = undefined;
        self.onResolvedCallbacks= [];
        self.onRejectedCallbacks= [];
        function resolve(value){
            self.status = 'resolved';
            self.value = value;
            self.onResolvedCallbacks.forEach(function(fn){
                fn();
            });
        }
        function reject(reason){
            self.status = 'rejected';
            self.reason = reason;
            self.onRejectedCallbacks.forEach(function(fn){
                fn();
            });
        }
    
        try{
            executor(resolve,reject);
        }catch(e){
            reject(e);
        }
    };
    
    Promise.prototype.then = function(onFulfilled,onRejected){
        let self = this;
        let promise2;           //实现链式操作
        if(self.status === 'resolved'){
            promise2 = new Promise(function(resolve, reject){
                try{
                    let x = onFulfilled(self.value);
                    resolve(x);
                }catch(e){
                    reject(e);
                }
            });
        }
        if(self.status === 'rejected'){
            promise2 = new Promise(function(resolve, reject){
                try{
                    let x = onRejected(self.reason);
                    reject(x);
                }catch(e){
                    reject(e);
                }
            });
        }
        if(self.status === 'pending'){
            promise2 = new Promise(function(resolve, reject){
                self.onResolvedCallbacks.push(function(){
                    try{
                        let x = onFulfilled(self.value);
                        resolve(x);
                    }catch(e){
                        reject(e);
                    }
                });
                self.onRejectedCallbacks.push(function(){
                    try{
                        let x = onRejected(self.reason);
                        reject(x);
                    }catch(e){
                        reject(e);
                    }
                });
            });
        }
        return promise2;
    }
    module.exports = Promise;
    

    当然他then的链式调用不会有then属性,所以我们可以判断Promise每次then都会new一个新的Promise我们用Promise2来表示,then的时候new一个新的Promise并且return给下一个then。
    then中无论是成功的回掉还是失败的毁掉,只要返回了结果,就会走下一个then中的成功,发生错误才会走下一个then中的失败,then中可以return普通值,也可return一个新的Promise,还有可能return 一个{then:xxx},当然更有promise.then().then.then(function(){});这种奇葩的用法

    function Promise(executor){
        let self = this;
        self.status = 'pending';
        self.value = undefined;
        self.reason = undefined;
        self.onResolvedCallbacks= [];
        self.onRejectedCallbacks= [];
        function resolve(value){
            self.status = 'resolved';
            self.value = value;
            self.onResolvedCallbacks.forEach(function(fn){
                fn();
            });
        }
        function reject(reason){
            self.status = 'rejected';
            self.reason = reason;
            self.onRejectedCallbacks.forEach(function(fn){
                fn();
            });
        }
        try{
            executor(resolve,reject);
        }catch(e){
            reject(e);
        }
    };
    
    function resolvePromise(p2,x,resolve,reject){
        //1.处理乱写
        //2.判断返回的是不是自己
        if(p2 === x){
            reject(new typeError('循环引用'));
        }
        //判断x是不是params(判断x是不是object)
        let called; //表示是否调用过成功或者失败
        if(x !== null || typeof x === 'object' || typeof x === 'function'){
            //判断promise只要判断对象中是否有then方法
            try{
                let then = x.then;
                if(typeof then === 'function'){ //then返回的可能是{then:xxx},判断then是不是一个函数
                    then.call(x,function(y){ //成功了以后可能会执行resolve(new Promise())用递归来解决
                        if(called) return;
                        called = true;
                        resolvePromise(p2,y,resolve,reject);
                    },function(err){
                        if(called) return;
                        called = true;
                        reject(err);
                    });
                }else{
                    resolve(x);
                }
            }catch(e){
                if(called) return;
                called = true;
                reject(e);
            }
        }else{  //esle普通值
            resolve(x);
        }
    }
    
    Promise.prototype.then = function(onFulfilled,onRejected){  //判断onFulfilled是不是一个函数,不是给他个函数
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(value){
            return value;
        }
        onRejected = typeof onRejected === 'function' ? onRejected : function(err){
            throw err;
        }
        let self = this;
        let promise2;           //实现链式操作
        if(self.status === 'resolved'){
            promise2 = new Promise(function(resolve, reject){
                let x = onFulfilled(self.value);
                resolvePromise(promise2,x,resolve,reject);
            });
        }
        if(self.status === 'rejected'){
            promise2 = new Promise(function(resolve, reject){
                let x = onRejected(self.reason);
                resolvePromise(promise2,x,resolve,reject);
            });
        }
        if(self.status === 'pending'){
            promise2 = new Promise(function(resolve, reject){
                self.onResolvedCallbacks.push(function(){
                    let x = onFulfilled(self.value);
                    resolvePromise(promise2,x,resolve,reject);
                });
                self.onRejectedCallbacks.push(function(){
                    let x = onRejected(self.reason);
                    resolvePromise(promise2,x,resolve,reject);
                });
            });
        }
        return promise2;
    }
    module.exports = Promise;
    

    我们就定义一个resolvePromise来处理then中的返回结果,如果返回的是个错误信息,就用try{}catch(){}让他走reject
    最后的最后,Promise中可以异步执行代码,then方法中应该也可以实现异步,很简单,只要在相应的位置加上setTimeout就ok了,记得不要忘了加上try{}catch(){}来过滤错误信息并且传到reject中

    function Promise(executor){
        let self = this;
        self.status = 'pending';
        self.value = undefined;
        self.reason = undefined;
        self.onResolvedCallbacks= [];
        self.onRejectedCallbacks= [];
        function resolve(value){
            self.status = 'resolved';
            self.value = value;
            self.onResolvedCallbacks.forEach(function(fn){
                fn();
            });
        }
        function reject(reason){
            self.status = 'rejected';
            self.reason = reason;
            self.onRejectedCallbacks.forEach(function(fn){
                fn();
            });
        }
        try{
            executor(resolve,reject);
        }catch(e){
            reject(e);
        }
    };
    
    function resolvePromise(p2,x,resolve,reject){
        //1.处理乱写
        //2.判断返回的是不是自己
        if(p2 === x){
            reject(new typeError('循环引用'));
        }
        //判断x是不是params(判断x是不是object)
        let called; //表示是否调用过成功或者失败
        if(x !== null || typeof x === 'object' || typeof x === 'function'){
            //判断promise只要判断对象中是否有then方法
            try{
                let then = x.then;
                if(typeof then === 'function'){ //then返回的可能是{then:xxx},判断then是不是一个函数
                    then.call(x,function(y){ //成功了以后可能会执行resolve(new Promise())用递归来解决
                        if(called) return;
                        called = true;
                        resolvePromise(p2,y,resolve,reject);
                    },function(err){
                        if(called) return;
                        called = true;
                        reject(err);
                    });
                }else{
                    resolve(x);
                }
            }catch(e){
                if(called) return;
                called = true;
                reject(e);
            }
        }else{  //esle普通值
            resolve(x);
        }
    }
    
    Promise.prototype.then = function(onFulfilled,onRejected){  //判断onFulfilled是不是一个函数,不是给他个函数
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(value){
            return value;
        }
        onRejected = typeof onRejected === 'function' ? onRejected : function(err){
            throw err;
        }
        let self = this;
        let promise2;           //实现链式操作
        if(self.status === 'resolved'){
            promise2 = new Promise(function(resolve, reject){
                setTimeout(function(){
                    try{
                        let x = onFulfilled(self.value);
                        resolvePromise(promise2,x,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                })
            });
        }
        if(self.status === 'rejected'){
            promise2 = new Promise(function(resolve, reject){
                setTimeout(function(){
                    try{
                        let x = onRejected(self.reason);
                        resolvePromise(promise2,x,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                })
            });
        }
        if(self.status === 'pending'){
            promise2 = new Promise(function(resolve, reject){
                self.onResolvedCallbacks.push(function(){
                    setTimeout(function(){   
                        try{
                            let x = onFulfilled(self.value);
                            resolvePromise(promise2,x,resolve,reject);
                        }catch(e){
                            reject(e);
                        }
                    })
                });
                self.onRejectedCallbacks.push(function(){
                    setTimeout(function(){
                        try{
                            let x = onRejected(self.reason);
                            resolvePromise(promise2,x,resolve,reject);
                        }catch(e){
                            reject(e);
                        }
                    })
                });
            });
        }
        return promise2;
    }
    module.exports = Promise;
    

    相关文章

      网友评论

          本文标题:Promise原理解析

          本文链接:https://www.haomeiwen.com/subject/ccvpqftx.html