手写 promise 练习

2022-04-13 18:00:56 浏览数 (1)

代码语言:javascript复制
/**
 * class MyPromise
 * for learn promise
 */
class MyPromise {
  state = 'pending' // 三种状态 不可逆改变 pending未完成 reject错误 fulfilled完成
  value = undefined // fulfilled 状态  返回结果
  reason = undefined // reject 状态  返回原因

  resolveCallBacks = [] // resolve事件回调数组
  rejectCallBacks = [] // reject事件回调数组

  constructor(fn) {
    // resolve 修改状态和结果
    const resolveHandler = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled'
        this.value = value
        this.resolveCallBacks.forEach(fn => {
          fn(value)
        })
      }
    }

    // reject 修改状态和原因
    const rejectHandler = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.reason = reason
        this.rejectCallBacks.forEach(fn => {
          fn(reason)
        })
      }
    }

    // 监听错误
    try {
      fn(resolveHandler, rejectHandler)
    } catch (err) {
      rejectHandler(err)
    }

  }

  // 链式调用 返回一个新的 MyPromise 对象
  then(fn1, fn2) {
    // 此处处理防止后续操作 常量被当作函数从而引发的错误
    fn1 = typeof fn1 === 'function' ? fn1 : (v) => {
      v
    }
    fn2 = typeof fn2 === 'function' ? fn2 : (e) => {
      e
    }

    // pending状态时候 将回调函数纳入各状态的回调数组 等待处理
    if (this.state === 'pending') {
      return new MyPromise((resolve,reject)=>{
        try {
          this.resolveCallBacks.push(()=>{
            fn1(this.value)
          })
          this.rejectCallBacks.push(()=>{
            fn2(this.reason)
          })
        }catch (e) {
          reject(e)
        }
      })
    }

    // fulfilled 回调触发 返回新的 fulfilled(resolve) 状态的 MyPromise 对象
    if (this.state === 'fulfilled') {
      return new MyPromise((resolve, reject) => {
        try {
          const newValue = fn1(this.value)
          resolve(newValue)
        } catch (e) {
          reject(e)
        }

      })
    }

    // rejected 回调触发 返回新的 rejected(reject) 状态的 MyPromise 对象
    if (this.state === 'rejected') {
      return new MyPromise((resolve, reject) => {
        try {
          const newReason = fn2(this.reason)
          reject(newReason)
        } catch (e) {
          reject(e)
        }
      })
    }


  }


  // 语法糖 只接收 rejected回调事件
  catch(fn) {
    return this.then(null, fn)
  }


}

// 实际返回一个新的 MyPromise 对象 但只做 resolve处理
MyPromise.resolve = function (value) {
  return new MyPromise((resolve,reject)=>{
    resolve(value)
  })
}

// 实际返回一个新的 MyPromise 对象 但只做 rejected处理
MyPromise.reject = function (reason) {
  return new MyPromise((resolve,reject)=>{
    reject(reason)
  })
}

// 执行多个MyPromise 完成后统一返回
MyPromise.all = function (promiseList = []) {
 return new MyPromise((resolve,reject)=>{
   const result = [];
   const length = promiseList.length;
   let resolveCount = 0;
   promiseList.forEach(p=>{
     p.then(v=>{
       result.push(v)
       resolveCount  
       if(resolveCount===length){
         resolve(result)
       }
     }).catch(e=>reject(e));
   })
 })
}

// 执行多个MyPromise 有一个完成就返回
MyPromise.race = function (promiseList = []) {
  return new MyPromise((resolve,reject)=>{
    let isResolved = false
    promiseList.forEach(p=>{
      p.then(v=>{
        if(!isResolved){
          resolve(v)
          isResolved = true
        }
      }).catch(e=>reject(e));

    })
  })
}

0 人点赞