Promise A+规范实现

219 阅读2分钟

一. Promise 实现的关键点:

1.首先是关于Promise三个状态的问题---
    Promise共有三个状态,分别是:
    1. pending状态;简单来说,即还未做出决定(接受或者拒绝)的状态,
    根据实际场景的需求,最终会变成接受或拒绝的状态,并且不可修改。
    2. resolved状态;即已经做出决定,表示接受的状态,且状态不可更改。
    3. rejected状态;即已经做出决定,表示拒绝的状态,且状态不可更改。
    
 **需要通过以上规则去实现Promise的构造函数**
 
2.除了状态之后,另一个就是链式调用的实现---
    解决链式调用的两个关键点:
    (a)调用then方法必须满足thenable形式的条件:
    假设x满足thenable条件有以下代码:

x!==null&&(typeof x === 'object'|| typeof x ==='function')&&typeof x.then ==='function'

b)实现链式调用传参的关键代码:

var x = onResolved(this.data);

二. 完整代码实现

class MyPromise{
  /**
   * 构造函数设计思路:Promise有三个状态 pending[该状态可以理解为待定状态,它可能会变成resolved也可能会变成rejected]、
   * resolved[该状态一经确定后不可改变,并接受一个value值]和rejected[该状态一经确定后不可改变,并接受一个reason]
   * Promise构造函数需要传入一个参数fn(resolve,reject) 
   * @param {*} fn 
   */
  constructor(fn){
    this.data = undefined;
    this.status = 'pending';
    this.onResolvedCallback = [];
    this.onRejectedCallback = [];
    let resolve = (value)=>{
      if(this.status === 'pending'){
        this.status = 'resolved';
        this.data = value;
        this.onResolvedCallback.forEach((item)=>{
          item(value);
        })
      }
    };
    let reject = (reason)=>{
      if(this.status==='pending'){
        this.status='rejected';
        this.data = reason;
        this.onRejectedCallback.forEach((item)=>{
          item(value);
        })
      }
    }
    try{
      fn(resolve,reject);
    }catch(e){
      reject(e);
    }
  }

 /**
 * @param {*} onResolved 
 * @param {*} onRejected 
 * @returns 
 */
  then(onResolved,onRejected){
    onResolved = typeof onResolved === 'function'?onResolved:function(value){ return value}; //onResolved和onRejected必须是函数 如果不是函数 会自动忽略并取出值
    onRejected = typeof onRejected === 'function'?onRejected:function(reason){ return reason};
    if(this.status==='resolved'){
      return new MyPromise((resolve,reject)=>{
        try{
          var x = onResolved(this.data);
          resolvePromise(this,x,resolve,reject);
        }catch(e){
          reject(e)
        }        
      });
    }
    if(this.status==='rejected'){
      return new MyPromise((resolve,reject)=>{
        try{
          var x = onRejected(this.data);
          resolvePromise(this,x,resolve,reject);
        }catch(e){
          reject(e);
        }
        
      });
    }
    //pending状态下需要将函数先放入回调数组里面暂存 当Promise状态为resolved或者rejected的时候再执行
    if(this.status==='pending'){
      return new MyPromise((resolve,reject)=>{
        this.onResolvedCallback.push(function(value){
          try{
            var x = onResolved(value);
            resolvePromise(this,x,resolve,reject);
          }catch(e){
            reject(e);
          }
        });
        this.onRejectedCallback.push(function(reason){
          try{
            var x = onRejected(reason);
          resolvePromise(this,x,resolve,reject);
          }catch(e){
            reject(e);
          }
        })
      });
    }
  }
}

function resolvePromise(promise2,x,resolve,reject){
  let throwFlag = false; //一个Promise最终只能有一种状态 这里使用flag作为标识 谁先执行就是谁的状态
  if(promise2 === x){
    reject(new Error('TypeError'));
  }
  if(x instanceof MyPromise){
    if(x.status === 'pending'){
      x.then((value)=>{
         resolvePromise(x,value,resolve,reject);
      },reject);
    }else{
      x.then(resolve,reject);
    }
    return
  }
  //以下判断语句是判断是否是thenable形式
  if(x!==null&&(typeof x === 'object'|| typeof x ==='function')&&typeof x.then === 'function'){
    try{
        x.then((v)=>{
        if(throwFlag) return
        throwFlag = true;
        resolvePromise(x,v,resolve,reject);
      },(r)=>{
        if(throwFlag) return
        throwFlag = true;
        reject(r);
      })
    }catch(e){
      if(throwFlag) return
      throwFlag = true;
      reject(e);
    }
  }else{
    resolve(x)
  }
}