实现一个promise

在大前端,越来越人来探究promise背后的真面目,今天我们就来实现一个符合promiseA+规范的promise。promise上的静态方法有resolve()、reject()、all()、race(),原型上的方法有then()、catch()、finally()。

1、基础框架

promiser的构造函数接收一个参数是executor函数,并且传入两个参数:resolve,reject。分别是异步操作成功的回调函数和异步操作失败后的回调函数。

promise有三个状态 等待(pending) 成功态 (fulfilled) 失败态(rejected)

默认情况是 pending ->  fulfilled
          pending ->  rejected 
          fulfilled不能和rejected相互转化复制代码

下面来看一下代码具体的实现:

function Promise(executor){  
    let self = this;  
    self.status = 'pending'  
    self.value = undefined;  
    self.reason = undefined;  
    self.onResolvedCallbacks = []; //异步时,存放成功的回调函数  
    self.onRejectedCallbacks = []; //异步时,存放失败的回调函数  
    // 只有状态是pending 参能进行状态的转化  
    function resolve(value) {    
        if(self.status === 'pending'){      
            self.value = value;      
            self.status = 'fulfilled';      
            self.onResolvedCallbacks.forEach(function (fn) {        
                fn(); //成功时调用循环调用成功的函数执行      
            });   
         } 
    }  
    function reject(reason) {    
        if(self.status === 'pending'){      
            self.reason = reason;      
            self.status = 'rejected';      
            self.onRejectedCallbacks.forEach(function (fn) {        
                fn();//失败时调用循环调用失败的函数执行      
            })    
        }  
    }  
    try{    
        executor(resolve, reject); // 如果执行这个executor执行时候抛出异常 应该走下一个then的失败  
    }catch(e){    
        reject(e);// 出错了   
    }
}复制代码

2、then方法

每个promise实例上都有一个then方法,then方法接受两个参数,onFulfilled和onRejected。判断状态成功的时候(fulfilled),调用onFulfilled函数,把成功的值传回。判断状态失败的时候(rejected),调用onRejected失败函数,把失败的值传回。

如果状态是pending,代表是异步执行,把onFulfilled和onRejected函数存起来,executor里resolve函数和reject函数执行的时候再调用。

Promise.prototype.then = function (onFulfilled, onRejected) {  
    let self = this;  
    if (self.status === 'fulfilled'){    
        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);    
        })  
    }}
复制代码

3、then方法链式调用

  • promise每次调用then后,返回一个新的promise(then方法成功后 返回的是一个新的promise,这个返回的promise会被执行,如果返回的promise是成功的,会把这个结果传递到外层的下一个then中)
  • 如果返回的是promise 用promise的成功或者失败 执行下一个then
  • 如果返回的是一个普通值 会走外层下一个then的成功
  • 如果执行的时候 抛出异常就会走到下一个次then中的失败
  • 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;  }  
    let self = this;  
    let promise2; //promise2就是我们每次调用then后返回的新的promise
    promise2 = new Promise(function (resolve,reject) {    
        if (self.status === 'fulfilled') {      
            // 这个返回值是成功函数的执行结果      
            setTimeout(() => {        
                try{          
                    let x = onFulfilled(self.value);            
                    resolvePromise(promise2, x, resolve, reject);        
                }catch(e){          
                    reject(e);        
                }      
            }, 0);    
        }    
        if (self.status === 'rejected') {      
            setTimeout(() => {        
               try{          
                    let x = onRejected(self.reason);          
                    resolvePromise(promise2, x, resolve, reject);        
                    }catch(e){          
                    reject(e)        
                }      
            },0)    
        }    
        if (self.status === 'pending') {      
            // 默认当前 new Promise  executor中是有异步的      
            self.onResolvedCallbacks.push(function () {        
                setTimeout(() => {          
                    try{            
                        let x = onFulfilled(self.value);            
                        resolvePromise(promise2, x, resolve, reject);          
                    }catch(e){            
                        reject(e)          
                    }        
                }, 0);      
             });    
            self.onRejectedCallbacks.push(function () {        
                setTimeout(() => {          
                    try{           
                        let x = onRejected(self.reason);            
                        resolvePromise(promise2, x, resolve, reject);          
                    }catch(e){
                        reject(e);          
                    }        
                }, 0);      
            })    
        }  
    });  
    return promise2;  
}复制代码

4、链式调用的核心方法

核心方法,处理成功或者失败执行的返回值和promise2的关系

function resolvePromise(promise2,x,resolve,reject) {  
    // 这个处理函数 需要处理的逻辑韩式很复杂的  
    // 有可能这个x 是一个promise  但是这个promise并不是我自己的  
    if(promise2 === x){   
        return reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise>'))  
    }  
    // 不单单需要考虑自己 还要考虑 有可能是别人的promise  let called; 
    // 文档要求 一旦成功了 不能调用失败  
    if((x!=null&&typeof x=== 'object') || typeof x === 'function'){    
        // 这样只能说 x 可能是一个promise    
        try{      
            // x = {then:function(){}}    
            let then = x.then; // 取then方法      
            if(typeof then === 'function'){        
                then.call(x,function (y) { 
                    // resolve(new Promise)          
                    if(!called){called = true;} else{ return;}          
                    resolvePromise(x,y,resolve,reject); //  递归检查promise        
                },function (r) {          
                    if (!called) { called = true; } else { return; }          
                        reject(r);        
                });      
            }else{ // then方法不存在        
                resolve(x); // 普通值      
            }    
        }catch(e){ // 如果取then方法出错了,就走失败      
            if (!called) { called = true; } else { return; }      
            reject(e);    
        }  
    }else{    
        resolve(x);  
    }
}复制代码

5、catch方法的实现

catch方法其实就是then方法,直接调用then方法,成功传null,失败把参数传进去就ok了。

Promise.prototype.catch = function (onRejected) {  
    return this.then(null, onRejected);
}复制代码

6、finally方法

无论成功还是失败,都要执行回调函数,并且把成功或者失败的值向下传递。

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

7、reject方法实现

Promise.reject = function (reason) {  
    return new Promise(function (resolve, reject) {    
        reject(reason);  
    })
}复制代码

8、resolve方法实现

Promise.resolve = function (value) {  
    return new Promise(function (resolve, reject) {    
        resolve(value);  
    })
}复制代码

9、all方法实现

Promise提供了一个 并发的方法 Promise.all 实现并发执行promise.all方法返回的结果是一个promise

Promise.all = function (promises) {  
    return new Promise(function (resolve, reject) {    
        let arr = [];    // 处理数据的方法    
        let i = 0;    
        function processData(index, data) {      
            arr[index] = data; //数组的索引和长度的关系      
            if (++i === promises.length) { 
                // 当数组的长度 和promise的个数相等时 说明所有的promise都执行完成了        
                resolve(arr);      
            }    
        }    
        for (let i = 0; i < promises.length; i++) {      
            let promise = promises[i];      
            if (typeof promise.then == 'function') {       
                promise.then(function (data) {          
                    processData(i, data); // 把索引和数据 对应起来 方便使用        
                }, reject)      
            } else {        
                processData(i, promise);      
            }    
        }  
    });
}复制代码

10、race方法实现

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);      
            }    
        }  
    })
}复制代码


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值