promise/A+ 源码实现


const PENDING = 'PENDING',
  FULFILLED = 'FULFILLED',
  REJECTED = 'REJECTED';


function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    // 防止死循环
    return reject(new TypeError('Chaining cycle detected for promise #<MyPromise>'))
  }

  let called = false;

  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    try {
      let then = x.then; // throw error
      // 是一个对象或者函数 并且有then方法   认为是一个promise
      if (typeof then === 'function') { 
        then.call(x, (y) => {
          if (called) return;
          called = true;
          resolvePromise(promise2, y, resolve, reject);
        }, (r) => {
          if (called) return;
          called = true;
          reject(r);
        })
      } else {
        resolve(x);
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    resolve(x);
  }
}

class MyPromise {
  constructor(executor) {
    // promise状态
    this.status = PENDING;
    // resolve的值
    this.value = undefined;
    // reject的原因
    this.reason = undefined;

    // 连续的resolve的回调函数
    this.onResolveCallbacks = [];
    // 连续的reject的回调函数
    this.onRejectedCallbacks = [];

    // 将resolve写成函数是因为promise中可以写异步任务(settimeout)
    const resolve = (value) => {
      if (this.status === PENDING) {
        // 修改promise状态
        this.status = FULFILLED;
        this.value = value;
        // 发布 (执行之前订阅的所有resolve函数)
        this.onResolveCallbacks.forEach((fn) => fn());
      }
    }

    const reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        // 发布
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    }

    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  // x 普通值  promise
  then(onFulfilled, onRejected) {

    // 如果是函数就执行  如果是空的则跳过当前then   ( .then().then() )
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };

    // 因为then中不能存在this   如果要实现链式调用,则需要返回一个promise对象
    let promise2 = new MyPromise((resolve, reject) => {
      // 检查当前promise的状态
      if (this.status === FULFILLED) {
        // 因为promise2要是用了,但是还没有生成,为了生成promise2  将使用到的promise2部分的代码用settimeout包裹  执行部分放在event loop
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value);
            // 为什么要写resolvePromise呢  因为onFulfilled的返回值类型不确定  可能还是一个promise或者是一个普通的数据类型   需要进一步判断
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }

      if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }


      // 
      // let promise = new Promise((resolve, reject)=>{
      //  ...
      // })
      // promise.then(()=>{setTimeout({resolve()})}
      // promise.then(()=>{setTimeout({resolve()})})
      // 
      // 因为setTimeout()异步执行,所以当执行then的时候 resolve还不能立即执行,所以需要发布订阅模式,先将需要执行的resolve回调函数放入队列中
      if (this.status === PENDING) {
        // 订阅
        this.onResolveCallbacks.push(() => {
          try {
            let x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
        this.onRejectedCallbacks.push(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      }
    });

    return promise2;
  }

  catch (errorCallback) {
    return this.then(null, errorCallback);
  }
}

module.exports = MyPromise;
posted @ 2020-09-07 19:08  MarkJacobs  阅读(125)  评论(0)    收藏  举报