Web 前端开发 前端开发那些事让前端飞

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

2018-01-16  本文已影响0人  JOKER_HAN

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

promise

  1. 创建Promise 方法
  2. Promise 接收一个 executor 回掉函数
  3. Promise 三个状态
  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);
  });
}

源码

参考资料

上一篇下一篇

猜你喜欢

热点阅读