手写Promise

41 阅读1分钟

手写Promise代码,供参考

const PENDING = "PENDING";
const FULFILLED = "FULLFILLED"; 
const REJECTED = "REJECTED";

class MyPromise{
  constructor(fn){
    
    this.state = PENDING;
    this.value = undefined;

    this.onFulfilledHandlers = [];
    this.onRejectedHandlers = [];
    try {
      fn(this._resolve.bind(this), this._reject.bind(this))
    } catch (error) {
      this._reject(error)
    }
  }
  _resolve(value){
    if(this.state !== PENDING) return
    this._changestate(FULFILLED,value)
    while(this.onFulfilledHandlers.length){
      this.onFulfilledHandlers.shift()(this.value)
    }
  }
  _reject(error){
    if(this.state !== PENDING) return
    this._changestate(REJECTED,error)
    while(this.onRejectedHandlers.length){
      this.onRejectedHandlers.shift()(this.value)
    }
  }
  _changestate(state_, value){
    this.state = state_;
    this.value = value;
  }

  then(onFulfilled, onRejected){
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : error => {throw error};

    const thenPromise = new MyPromise((resolve, reject) =>{
      if(this.state === FULFILLED){
        try {
          queueMicrotask(() => {
            const resolveRes = onFulfilled(this.value);
            handlePromise(resolveRes, thenPromise, resolve, reject);
          })
        } catch (error) {
          reject(error);
        }
      } else if (this.state === REJECTED){
        try {
          queueMicrotask(() => {
            const rejectRes = onRejected(this.value);
            handlePromise(rejectRes, thenPromise, resolve, reject);
          })
        } catch (error) {
          reject(error);
        }
      } else{
        this.onFulfilledHandlers.push(() => {
          try {
            let fulfilledRes = onFulfilled(this.value)
            handlePromise(fulfilledRes, thenPromise,resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
        this.onRejectedHandlers.push(() => {
          try {
            let rejectRes = onRejected(this.value)
            handlePromise(rejectRes, thenPromise,resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
      }
    })
    return thenPromise
  }
}

function handlePromise(promiseres, thenpromise, resolve, reject){
  if(promiseres === thenpromise){
    throw new Error("can not be self")
  }
  if(promiseres instanceof MyPromise){
    promiseres.then(resolve, reject)
  } else {
    resolve(promiseres)
  }
}

const promise = new MyPromise((resolve) => {
  setTimeout(() => {
    resolve(1000)
  }, 1000)
})

promise.then(res => {
  console.log(res)
}).then(res => {
  console.log(res)
  return new MyPromise(resolve => resolve(3000))
}).then(res => {
  console.log(res);
})