class MyPromise {
  static STATE_MAPPING = {
    PENDING: 'pending',
    RESOLVED: 'resolved',
    REJECTED: 'rejected',
  }

  constructor(props) {
    this.status = MyPromise.STATE_MAPPING.PENDING;
    this.data = undefined;
    this.resolvedCallbacks = [];
    this.rejectedCallbacks = [];
    this.fn = props;
    this.doTask();
  }

  doTask = () => {
    const { resolve, reject } = this;
    try {
      this.fn(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }

  resolve = (data) => {
    if (this.status === MyPromise.STATE_MAPPING.PENDING) {
      this.status = MyPromise.STATE_MAPPING.RESOLVED;
      this.data = data;
      this.resolvedCallbacks.forEach(cb => cb(data));
    }
  }

  reject = (data) => {
    if (this.status === MyPromise.STATE_MAPPING.PENDING) {
      this.status = MyPromise.STATE_MAPPING.REJECTED;
      this.data = data;
      this.rejectedCallbacks.forEach(cb => cb(data));
    }
  }

  handleResolve = (resolve, reject, handler) => {
    try {
      const ret = handler(this.data);
      if (ret instanceof MyPromise) {
        ret.then(resolve, reject);
      } else {
        resolve(ret);
      }
    } catch (e) {
      reject(e);
    }
  }

  handleReject = (resolve, reject, handler) => {
    try {
      const ret = handler(this.data);
      if (ret instanceof MyPromise) {
        ret.then(resolve, reject);
      } else {
        reject(ret);
      }
    } catch (e) {
      reject(e);
    }
  }

  then = (onFulfilled, onRejected) => {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
    onRejected = typeof onRejected === 'function' ? onRejected : e => {throw e};
    const actions = {
      resolved: () => new MyPromise((resolve, reject) => setTimeout(() =>
        this.handleResolve(resolve, reject, onFulfilled)
      )),
      rejected: () => new MyPromise((resolve, reject) => setTimeout(() =>
        this.handleReject(resolve, reject, onRejected)
      )),
      pending: () => new MyPromise((resolve, reject) => {
        this.resolvedCallbacks.push(() => setTimeout(() =>
          this.handleResolve(resolve, reject, onFulfilled)
        ));
        this.rejectedCallbacks.push(() => setTimeout(() =>
          this.handleReject(resolve, reject, onRejected)
        ));
      }),
      default: () => {
        throw new Error('sth may happened ~')
      },
    };
    return actions[this.status]
      ? actions[this.status]()
      : actions.default();
  }

  catch = (onRejected) => {
    return this.then(null, onRejected);
  }
}


new MyPromise((resolve, reject) => {
  reject('失败');
}).then().then().then(data => {
  console.log('成功');
}, err => {
  console.log('失败');
})

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

算法感悟 上一篇
leetCode刷题(六)二叉树题目集合 下一篇