JavaScript:手撕Promise

const PENDING = "pending" //待解决的
const FULFILLED = "fulfilled" //已实现
const REJECTED = "rejected" //已失败

class MyPromise {
  state = PENDING
  value = undefined
  callbacks = []

  constructor(executor) {

    try {
      executor(this._resolve.bind(this), this._reject.bind(this))
    } catch (error) {
      this._reject(error)
    }
  }

  _resolve(value) {
    if (this.state !== PENDING) return;
    if (typeof value === 'object' && value instanceof MyPromise) {
      value.then(this._resolve.bind(this), this._reject.bind(this))
    } else {
      this.state = FULFILLED;
      this.value = value
      this.callbacks.forEach(callback => this._handle(callback))//交给_handle去调用callback
    }
  }

  _reject(reason) {
    if (this.state !== PENDING) return;
    if (typeof reason === 'object' && reason instanceof MyPromise) {
      reason.then(this._resolve.bind(this), this._reject.bind(this));
    } else {
      this.state = REJECTED;
      this.value = reason
      this.callbacks.forEach(callback => this._handle(callback))//交给_handle去调用callback
    }
  }

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this._handle({onFulfilled, onRejected, resolve, reject})
    })
  }

  catch(onError) {
    return this.then(null,onError)
  }

  finally(onDone) {
    if (typeof onDone !== 'function') {
      return this.then()
    } else {
      return this.then(
        value => MyPromise.resolve(onDone()).then(() => value),
        reason => MyPromise.resolve(onDone()).then(() => {
          throw reason
        })
      );
    }
  }

  //回调函数处理器
  _handle(callback) {
    if (this.state === PENDING) {
      this.callbacks.push(callback)
    } else {
      try {
        if (this.state === FULFILLED) {
          let res = (typeof callback.onFulfilled) === 'function' ? callback.onFulfilled(this.value) : this.value
          callback.resolve(res)
        } else if(this.state === REJECTED) {
          if(typeof callback.onRejected === 'function'){
            //有处理Rejected的回调函数则处理并使下一个Promise处于成功态
            let res = callback.onRejected(this.value)
            callback.resolve(res)
          }else{
            //没有则说明还没处理,继续报错下去
            callback.reject(this.value)
          }
        }
      } catch (error) {
        callback.reject(error)
      }
    }
  }

  //静态函数区域
  static resolve(value) {
    if (typeof value === 'object' && value instanceof MyPromise) {
      return value
    } else if (value && typeof value === 'object' && typeof value.then == 'function') {
      //value == { then:(onFulfilled)=>{...,onFulfilled(someVal)} }
      return new MyPromise(resolve => value.then(resolve))
    } else {
      return new MyPromise(resolve => resolve(value))
    }
  }

  static reject(reason) {
    if (reason && typeof reason === 'object' && typeof reason.then == 'function') {
      return new MyPromise((resolve, reject) => reason.then(reject))
    } else {
      return new MyPromise(resolve => resolve(reason))
    }
  }

  static all(promiseList) {
    return new MyPromise((resolve, reject) => {
      let res = []
      let fulfilledCount = 0
      promiseList.forEach((promise, index) => {
        MyPromise.resolve(promise).then(result => {
          res[index] = result
          fulfilledCount++
          if (onFulfilledNum === promiseList.length) resolve(res)
        }).catch(err => {
          res[index] = err
          reject(err)
        })
      })
    })
  }

  static race(promiseList) {
    return new MyPromise((resolve, reject) => {
      promiseList.forEach((promise, index) => {
        MyPromise.resolve(promise).then(result => {
          resolve(result)
        }).catch(err => {
          reject(err)
        })
      })
    })
  }
}




test(Promise)
test(MyPromise)
function test(PromiseClass){
  new PromiseClass((resolve, reject) => {
    setTimeout(() => {
      console.log(PromiseClass.prototype.constructor)
      resolve(1)
    }, 500)
  }).then(res => {
    console.log('A', res)
    return new PromiseClass((resolve, reject)=>{
      resolve(321)
    })
  }).catch(err => {
    console.log('B', err)
  }).catch(err => {
    console.log('C', err)
  }).then(res=>{
    console.log('CC',res)
  }).catch(err => {
    console.log('D', err)
  }).finally(() => {
    console.log('Finish')
  })
}

参考链接:
https://zhuanlan.zhihu.com/p/58428287
https://juejin.cn/post/6844904063570542599

发表评论

您的电子邮箱地址不会被公开。