1. 手写Promise

127 阅读2分钟

手写Promise

/**
 * 1. then方法中,成功的回调或者失败的回调返回的是一个promise,会采用promise返回的状态,走外层下一个then中的成功或者失败
 * 同时将promise处理的结果向下传递 (返回的promise成功 就走到外层then的成功;否则走到外层then的失败)
 * 2. then方法中,如果成功地回调或者失败的回调返回的是一个普通值(不是promise),会将返回的结果传到下一次then的成功中
 * 3. then方法中, 如果成功的回调或者失败的回调中抛出异常,会走到下一次then的失败中
 * 小结: 如果返回的是失败的promise或者抛错,就会走到下一个then的失败中去,否则走到下一个then的成功中
 * 
 * 如何实现链式调用: 每次都产生一个全新的promise,保证状态可以正常切换
 */
const PENDING = 'pending';
const FULFIILED = 'fulfilled';
const REJECTED = 'rejected';

class Promise {
  constructor(executor) {
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = value => {
      if(this.status === PENDING) {
        this.status = FULFIILED;
        this.value = value;
        this.onResolvedCallbacks.forEach(fn => fn());
      }
    }

    const reject = reason => {
      if(this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        this.onResolvedCallbacks.forEach(fn => fn());
      }
    }

    // new Promise的时候可能会抛错
    // new Promise((resolve,reject) => {
    //   throw new Error()
    // })
    // 所以用try catch包裹
    try{
      executor(resolve, reject);
    }catch(e){
      reject(e);
    }

  }

  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v=> v;
    onRejected = typeof onRejected === 'function'? onRejected : e => {throw e}
    // 每次调用then方法,都返回一个全新的promise
    let promise2 = new Promise((resolve,reject) => { // x就是上一个then成功或者失败的返回值,这个x决定promise2走成功还是失败
      if(this.status === FULFIILED) {
        setTimeout(() => {
          try{
            let x = onFulfilled(this.value);
            // 将then的回调中的返回值传递到下一个then中
            resolvePromise(x,promise2, resolve, reject);
          }catch(e) {
            reject(e)
          }
        }, 0);
      }
      if(this.status === REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(x,promise2, resolve, reject);
          }catch(e) {
            reject(e);
          }
        }, 0);
      }
      if(this.status === PENDING) {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try{
              let x = onFulfilled(this.value);
              resolvePromise(x,promise2, resolve, reject);
            }catch(e) {
              reject(e)
            }
          }, 0);
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(x,promise2, resolve, reject);
            }catch(e) {
              reject(e);
            }
          }, 0);
        })
      }
    });
    return promise2;
  }
}

function resolvePromise(x, promise2, resolve, reject) {
  if(x === promise2) {
    return reject(new TypeError("循环引用"))
  }
  // 如果x是一个普通值 则直接调用resolve
  // 如果x是一个promise, 应该采用这个promise的状态 决定调用resolve还是reject
  if((typeof x === 'object' && x !== null) || typeof x === 'function') {
    // 才有可能是promise,继续判断是否有then
    let called = false;
    try{// 防止取then时抛错
      let then = x.then; //尝试取then方法
      if(typeof then === 'function') { // 就认为是promise了
        then.call(x, (y) => { // y有可能还是一个promise,所以要再次进行解析
          if(called) return;
          called = true;
          resolvePromise(y, promise2, resolve, reject)
        }, (r) => {
          if(called) return;
          called = true;
          reject(r)
        });
      }else{
        resolve(x);
      }
    }catch(e) {
      if(called) return;
      called = true;
      reject(e);
    }

  }else{
    // x是一个普通值
    resolve(x);
  }

}