用JS手写一个简单的Promise

参照Promise/A+规范手写了一个简化版的promise

class MyPromise {
  constructor(fn) {
    if (typeof fn !== 'function') {
      throw new Error('参数必须为函数');
    }
    this._state = 'Pending';   //promise目前的状态
    this._value = null;     //用于存储promise终值
    this._reason = null;    //用于存储promise拒因
    this.fulfillCallbacks = [];   //存储resolve的回调函数
    this.rejectCallbacks = [];    //存储reject的回调函数

    fn(this._resolve.bind(this), this._reject.bind(this));
  }

  // 将promise转化为Fulfilled状态,并依次执行then注册的onFulfilled回调函数
  _resolve(value) {
    if (this._state !== 'Pending') return;

    let run = () => {

      let runFulfill = (val) => {
        this._state = 'Fulfilled';
        this._value = val;

        let cb;
        while(cb = this.fulfillCallbacks.shift()) {
          cb(value);
        }
      }

      let runReject = (err) => {
        this._state = 'Rejected';
        this._reason = err;

        let cb;
        while(cb = this.rejectCallbacks.shift()) {
          cb(err);
        }
      }

      if (value instanceof MyPromise) {
        value.then(runFulfill, runReject);
      } else {
        runFulfill(value);
      }
    }

    process.nextTick(run);

  }

  // 将promise转化为Rejected状态,并依次执行then注册的onRejected回调函数
  _reject(error) {
    if (this._state !== 'Pending') return;

    let run = () => {
      this._state = 'Rejected';
      this._reason = error;

      let cb;
      while(cb = this.rejectCallbacks.shift()) {
        cb(error);
      }
    }

    process.nextTick(run);
  }

  // 注册回调函数,返回新的promise实例
  then(onFulfilled, onRejected) {

    let newPromise;

    return newPromise = new MyPromise((nextResolve, nextReject) => {
    // 由于当前promise注册的回调函数返回值影响着新promise的状态
    // 因此需要包装一下原来的回调函数
      let fulfillFunc = value => {        
        if (typeof onFulfilled === 'function') {
          try {
            let res = onFulfilled(value);
            MyPromise.resolvePromise(newPromise, res);
          } catch(e) {
            nextReject(e);
          }
        } else {
          nextResolve(this._value);
        }
      }

      let rejectFunc = value => {
        if (typeof onRejected === 'function') {
          try {
            let res = onRejected(value);
            MyPromise.resolvePromise(newPromise, res);
          } catch(e) {
            nextReject(e);
          }
        } else {
          nextReject(this._reason);
        }
      }

		// 将包装后的回调函数推入对应的回调函数数组
      if (this._state === 'Pending') {
        this.fulfillCallbacks.push(fulfillFunc);
        this.rejectCallbacks.push(rejectFunc);
      } else if (this._state === 'Fulfilled') {
        fulfillFunc(this._value);
      } else if (this._state === 'Rejected') {
        rejectFunc(this._reason);
      }
    });
  }

  catch(onRejected) {
    return this.then(undefined, onRejected);
  }

  finally(callBack) {
    return this.then(
      (value) => MyPromise.resolve(callBack()).then(() => value),
      (err) => MyPromise.resolve(callBack()).then(() => err)
    )
  }

  // promise的解决过程
  static resolvePromise(promise, val) {
    if (val === promise) {
      throw new Error('TypeError');
    } else if (val instanceof MyPromise) {
      if (val._state === 'Fulfilled') {
        promise._resolve(val._value);
      } else if (val._state === 'Rejected') {
        promise._reject(val._reason);
      } else {
        val.then(promise._resolve.bind(promise), promise._reject.bind(promise));
      }
    } else if (typeof val === 'object' || typeof val === 'function') {
      let then;
      try {
        then = val.then;
      } catch(e) {
        promise._reject(e);
      }
      if (typeof then === 'function') {
        then.call(val, function(value){
          this.resolvePromise(promise, value)
        }, nextReject)
      } else {
        promise._resolve(val);
      }
    } else {
      promise._resolve(val);
    }
  }

  static resolve(value) {
    if (value instanceof MyPromise) return value;
    return new MyPromise(resolve => resolve(value));
  }

  static reject(value) {
    return new MyPromise((resolve, reject) => reject(value));
  }

  static all(promises) {
    if (!Array.isArray(promises)) throw new Error('参数必须为数组');

    return new MyPromise((resolve, reject) => {
      let values = [];
      let count = 0;

      for (let i=0; i<promises.length; i++) {
        this.resolve(promises[i]).then(value => {
          values[i] = value;
          count++;

          if (count === promises.length) resolve(values);
        }, (err) => {
          reject(err);
        });
      }
    });
  }

  static race(promises) {
    if (!Array.isArray(promises)) throw new Error('参数必须为数组');

    return new MyPromise((resolve, reject) => {

      for (let i=0; i<promises.length; i++) {
        this.resolve(promises[i]).then(value => {
          resolve(value);
        }, (err) => {
          reject(err);
        });
      }
    });
  }
}

你可能感兴趣的:(Javascript笔记)