手写promise

2019-10-14  本文已影响0人  皮神雷卡丘

1)构造函数中立即执行函数
2)resolve和reject,Promise.resolve()这样的方法是存在于构造函数的方法,在es6中用static关键字
3)状态机
4)实现then(链式调用),then应该返回同自己类型的promise,并且是全新的对象
5)实现resolve的异步调用,用了asyncQueue一个队列,将then传入的回调函数推入队列,没有调用resolve之前一定为pending状态,此时调用then就返回自身,得以保存队列完整,调用resolve之后再for循环 同步阻塞调用执行,返回一个全新的promise进行迭代
(resolvePromise)是Promise处理的一个标准

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

export default class MyPromsie<T> {

  private state: string = '';
  private val: string = '';
  private reason: string = '';
  // 实现异步调用队列
  private asyncQueue: IPromiseCBS[] = [];

  constructor(executor: <T = any>(resolve?: (value?: any) => void, reject?: (reason?: any) => void) => void) {
    // 初始化状态机
    this.state = PENDING;

    try {
      executor((val: any) => { this.resolve(val) }, (reason: any) => { this.reject(reason) });
    } catch (reason) {
      this.reject(reason);
    }
  }
  // then function
  public then(onFulfilled?: (val: any) => any, onRejected?: (reason: any) => any): MyPromsie<T> {
    let promise: MyPromsie<T>;
    // 异步情况 还未通过resolve改变pending状态
    if (this.state === PENDING) {
      // 箭头函数 阻止this 丢失
      const ele = { onFulfilled, onRejected } as IPromiseCBS;
      this.asyncQueue.push(ele);
      return this;
    }
    promise = new MyPromsie((resolve, reject) => {
      if (this.state === FULFILLED) {
        // onFuifilled 的参数为 fulfilled 状态时的val值,并返回一个新的值作为新的promise resolve的入参
        try {
          const x = onFulfilled(this.val)
          resolve(x);
        } catch (reason) {
          reject(reason);
        }
      }

      if (this.state === REJECTED) {
        try {
          const x = onRejected(this.reason)
          // todo resolvePromise()
          resolve(x);
        } catch (reason) {
          reject(reason);
        }
      }
    });
    console.log(promise);
    return promise;
  }

  public catch() {

  }

  public finally() {

  }

  private resolve(val: any) {
    if (this.state === PENDING) {
      this.state = FULFILLED;
      // 保存调用resolve的值
      this.val = val;
      this.queueExecutor();
    }
  }

  private reject(reason: any) {
    if (this.state === PENDING) {
      this.state = REJECTED;
      // 保存调用reject的值
      this.reason = reason;
      this.queueExecutor();
    }
  }

  private queueExecutor() {
    // 如果resolve被异步调用 队列必不为空
    if (this.asyncQueue.length > 0) {
      let promise: MyPromsie<any> = this;
      // for 循环为 同步 阻塞调用
      for (let index = 0; index < this.asyncQueue.length; index++) {
        const element = this.asyncQueue[index];
        promise = promise.then(element.onFulfilled, element.onRejected);
      }
    }
  }
  // Promise.resolve()
  static resolve(val: any) {
    console.log(`static resolve val = ${val}`)
  }
  // Promise.reject()
  static reject(reason: any) {
    console.log(`static reject reason = ${reason}`)
  }

}

interface IPromiseCBS {
  onFulfilled?: (val: any) => any;
  onRejected?: (reason: any) => any;
}

实现Promise.all .race resolve reject,最终为

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

export default class MyPromsie<T> {

  private state: string = '';
  private val: string = '';
  private reason: string = '';
  // 实现异步调用队列
  private asyncQueue: IPromiseCBS[] = [];

  constructor(executor: <T = any>(resolve?: (value?: any) => void, reject?: (reason?: any) => void) => void) {
    // 初始化状态机
    this.state = PENDING;

    try {
      executor((val: any) => { this.resolve(val) }, (reason: any) => { this.reject(reason) });
    } catch (reason) {
      this.reject(reason);
    }
  }
  // then function
  public then(onFulfilled?: (val: any) => any, onRejected?: (reason: any) => any): MyPromsie<T> {
    let promise: MyPromsie<T>;
    // 异步情况 还未通过resolve改变pending状态
    if (this.state === PENDING) {
      // 箭头函数 阻止this 丢失
      const ele = { onFulfilled, onRejected } as IPromiseCBS;
      this.asyncQueue.push(ele);
      return this;
    }
    promise = new MyPromsie((resolve, reject) => {
      if (this.state === FULFILLED) {
        // onFuifilled 的参数为 fulfilled 状态时的val值,并返回一个新的值作为新的promise resolve的入参
        try {
          const x = onFulfilled(this.val)
          resolve(x);
        } catch (reason) {
          reject(reason);
        }
      }

      if (this.state === REJECTED) {
        try {
          const x = onRejected(this.reason)
          // todo resolvePromise()
          resolve(x);
        } catch (reason) {
          reject(reason);
        }
      }
    });
    // console.log(promise);
    return promise;
  }
  // 实质为 onFuifilled 回调为空
  public catch(onRejected?: (reason: any) => any) {
    this.then(null,onRejected);
  }
  // finally 总是被执行的 无论成功还是 promise被拒绝 先执行.then中 成功或者失败的回调再调用finally的回调函数
  public finally(cbs: Function) {
    cbs();
  }

  private resolve(val: any) {
    if (this.state === PENDING) {
      this.state = FULFILLED;
      // 保存调用resolve的值
      this.val = val;
      this.queueExecutor();
    }
  }

  private reject(reason: any) {
    if (this.state === PENDING) {
      this.state = REJECTED;
      // 保存调用reject的值
      this.reason = reason;
      this.queueExecutor();
    }
  }

  private queueExecutor() {
    // 如果resolve被异步调用 队列必不为空
    if (this.asyncQueue.length > 0) {
      let promise: MyPromsie<any> = this;
      // 这么写 如果onFulfilled onRejected如果有异步函数 依然是有问题的啊  得不到顺序执行
      for (let index = 0; index < this.asyncQueue.length; index++) {
        const element = this.asyncQueue[index];
        promise = promise.then(element.onFulfilled, element.onRejected);
      }
    }
  }
  // Promise.resolve()
  static resolve(val?: any) {
    console.log(`static resolve val = ${val}`)
    return new MyPromsie((resolve, reject) => {
      resolve(val);
    });
  }
  // Promise.reject()
  static reject(reason?: any) {
    console.log(`static reject reason = ${reason}`)
    return new MyPromsie((resolve, reject) => {
      reject(reason);
    });
  }
  // 输入promise数组 哪个promise 先执行完就返回哪个
  static race(pArray: MyPromsie<any>[]) {
    return new MyPromsie((resolve, reject) => {
      for (let i = 0; i < pArray.length; i++) {
        pArray[i].then(resolve, reject)
      };
    })
  }
  // all方法(获取所有的promise,都执行then,把结果放到数组,一起返回)
  // 如果有其中一个被 reject 则返回第一个失败的promise
  static all(pArray: MyPromsie<any>[]) {

    const arr = Array(pArray.length);
    let i: number = 0;
    return new MyPromsie((resolve, reject) => {
      for (let index = 0; index < pArray.length; index++) {
        const promise = pArray[index];
        promise.then(val => {
          arr[index] = val;
          if (++i == pArray.length) {
            // 注意这里只能等异步调用返回结果之后才能resolve
            resolve(val);
          };
        }, reason => {
          console.log(reason)
          reject(reason);
        });
      }
    });
  }
}

interface IPromiseCBS {
  onFulfilled?: (val: any) => any;
  onRejected?: (reason: any) => any;
}
上一篇下一篇

猜你喜欢

热点阅读