实现符合 Promise/A+ 规范的Promise

作者: JOKER_HAN | 来源:发表于2018-01-16 20:15 被阅读0次

    实现一个符合 Promise/A+ 规范的 MyPromise,并实现 resolve、reject、all、race等静态方法。

    promise

    1. 创建Promise 方法
    2. Promise 接收一个 executor 回掉函数
    3. Promise 三个状态
    • pedding
      • 可以变为 fulfilled 成功态 或者 rejected 失败态
    • fulfilled
      • 不可改变的成功态
    • rejected
      • 不可改变失败态
    1. onResolvedCallbacks和onRejectedCallbacks
      • 分别存储成功 成功和失败的回调函数
    2. resolve
      • promise专向成功态调用的函数,接收value参数
    3. reject
      • promise转向失败态调用的函数,接受reason参数
    function  Promise(executor) {
        let self = this;
        self.status = 'pending';
        //存放成功回调的数组
        self.onResolvedCallbacks =[];
        //存放失败回调的数组
        self.onRejectedCallbacks =[];
        
        function resolve(value) {
            if(self.status == 'pending'){
                self.status = 'fulfilled';
                self.value = value;//成功后得到一个值,这个值不能改
                self.onResolvedCallbacks.forEach(cb=>cb(self.value))//
    
            }
        }
        function reject(reason) {
            if(self.status == 'pending'){
                self.status = 'rejected';
                self.value = reason;
                self.onRejectedCallbacks.forEach(cb=>cb(self.value))
            }
        }
        try{
            executor(resolve,reject)
        }catch (e){
            //如果函数执行失败了,reject这个promise
            reject(e)
        }
    }
    

    Promise.prototype.then

    链式调用返回一个新的Promise,将第一次的返回值,作为下一次成功回掉函数的参数

    1. onFulfilledonRejected
      • 一个promise.then方法接收两个参数onFilfiledonRejected
      • 如果成功和失败的回调没有传,则表示这个then没有任何逻辑,只会把值往后抛
    2. onFulfilled
      • 成功时调用
      • 并把成功的结果传递给onFulfilled
      • 不能调用多次
    3. onRejected
      • 失败时调用
      • 并把失败的结果传递给onRejected
      • 不能调用多次
    4. then会调用多次,之后返回一个新的promise
      • promise2 = promise1.then(onFulfilled, onRejected)
      • 如果 onFulfilledonRejected返回x解析promise 执行 resolvePromise方法
    Promise.prototype.then = function (onFulfilled,onRejected) {
        onFulfilled = typeof onFulfilled == 'function'?onFulfilled:value=>value;
        onRejected = typeof onRejected == 'function'?onRejected:reason=>{throw reason};
        let self = this;
        let promise2;
        //当前promise已经是成功态了,onFulfilled直接取值
        if(self.status == 'fulfilled'){
            return promise2 = new Promise(function (resolve,reject) {
                try{
                    let x = onFulfilled(self.value);
                    resolvePromise(promise2,x,resolve,reject)
                }catch (e){
                    reject(e)
                }
    
            });
        }
        if(self.status == 'rejected'){
           return promise2 = new Promise(function (resolve,reject) {
               try{
                   let x = onRejected(self.value);
                   resolvePromise(promise2,x,resolve,reject)
               }catch (e){
                   reject(e)
               }
           })
        }
        if(self.status == 'pending'){
            return promise2 = new Promise(function(resolve,reject){
                self.onResolvedCallbacks.push(function(){
                    try{
                        let x =onFulfilled(self.value);
                        //如果获取到了返回值x,会走解析promise的过程
                        resolvePromise(promise2,x,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
    
                });
                self.onRejectedCallbacks.push(function(){
                    try{
                        let x =onRejected(self.value);
                        resolvePromise(promise2,x,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                });
            });
        }
    
    };
    

    The Promise resolvePromise 解析方法

    1. 如果x===当前promise2 不能返回当前Promise,那么会抛出错误 new TypeError('循环引用')
    2. x是一个Promise
      • 当前promise2等待x完成,x有可能也是一个Promise 执行resolvePromise()
    3. x 如果不是对象(不包括 null)或者函数,执行 resolve(x)
    4. 获取 x.then 赋值给 then
      • then 如果是 function
        • 把 x做为 this 调用then,第一个参数是 resolvePromise2,第二个参数是 rejectPromise2
        • resolvePromise2rejectPromise2只有第一次调用有效
        • resolvePromise2参数为 y,执行 resolvePromise(promise, y, resolve, reject)
      • then 如果不是 function
        • 执行resolve(x)
    function resolvePromise(promise2,x,resolve,reject){
      if(promise2 === x){
        return reject(new TypeError('循环引用'));
      }
      let called = false;//promise2是否已经resolve 或reject了
      if(x instanceof Promise){
        if(x.status == 'pending'){
          x.then(function(y){
            resolvePromise(promise2,y,resolve,reject);
          },reject);
        }else{
          x.then(resolve,reject);
        }
      //x是一个thenable对象或函数,只要有then方法的对象,
      }else if(x!= null &&((typeof x=='object')||(typeof x == 'function'))){
       try{
         let then = x.then;
         if(typeof then == 'function'){
           //有些promise会同时执行成功和失败的回调
           then.call(x,function(y){
             //如果promise2已经成功或失败了,则不会再处理了
              if(called)return;
              called = true;
              resolvePromise(promise2,y,resolve,reject)
           },function(err){
             if(called)return;
             called = true;
             reject(err);
           });
         }else{
           //到此的话x不是一个thenable对象,那直接把它当成值resolve promise2就可以了
           resolve(x);
         }
       }catch(e){
         if(called)return;
         called = true;
         reject(e);
       }
    
      }else{
        //如果X是一个普通 的值,则用x的值去resolve promise2
        resolve(x);
      }
    }
    

    Promise.prototype.catch

    1. 只传失败的回掉
    Promise.prototype.catch = function(onRejected){
      this.then(null,onRejected);
    }
    

    Promise.all

    1. 接收Promise数组,全部完成才会成功,有一个失败,整个Promise失败
    function gen(times,cb){
      let result = [],count=0;
      return function(i,data){
        result[i] = data;
        if(++count==times){
          cb(result);
        }
      }
    }
    Promise.all = function(promises){
     return new Promise(function(resolve,reject){
       let done = gen(promises.length,resolve);
       for(let i=0;i<promises.length;i++){
         promises[i].then(function(data){
           done(i,data);
         },reject);
       }
     });
    }
    

    Promise.race

    1. 接收Promise数组,一个成功就成功了,一个失败就失败了
    Promise.race = function(promises){
      return new Promise(function(resolve,reject){
        for(let i=0;i<promises.length;i++){
          promises[i].then(resolve,reject);
        }
      });
    }
    

    Promise.resolve

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

    Promise.reject

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

    源码

    参考资料

    相关文章

      网友评论

        本文标题:实现符合 Promise/A+ 规范的Promise

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