手写Promise其他方法实现

106 阅读6分钟

Promise的其他方法实现

前面,我们手写的Promise.then的实现 手写PromiseA+ ,对于Promise的其他方法,比then方法简单的多

catch 和 finally 实现

catch 实现

class MyPromise {
  // ... 忽略
  
  /**
   * 对于 catch 的处理
   * @param {Function} errorExcute 
   * @returns 
   */
  catch(errorExcute) {
    return this.then(null, errorExcute)
  }
}

finally 实现

  1. Promise失败还是成功, 并不影响finally的执行
  2. finally函数执行返回结果, 并不会影响Promise结果
  3. finally函数执行过程中出现错误, 会影响到Promise状态和结果
  /**
   * 对于 finally 的处理
   * 1. Promise失败还是成功, 并不影响finally的执行
   * 2. finally函数执行返回结果, 并不会影响Promise结果
   * 3. finally函数执行过程中出现错误, 会影响到Promise状态和结果
   * @param {Function} settledExcuter 
   * @returns 
   */
  finally(settledExcuter) {
    settledExcuter = typeof settledExcuter === 'function' ? sureExcuter : () => {}      
    return this.then((data) => {
      settledExcuter()
      return data
    }, (reason) => {
      settledExcuter()
      throw reason
    })
  }

resolve 和 reject 实现

resolve 实现

  • 根据传入参数产生以下情况
  1. 参数为Promise, 直接返回这个Promise
  2. 参数为PromiseLike, 使用resolve吸收PromiseLike, 状态和结果与PromiseLike一致
  3. 参数为其他, 直接resolve(值)
  /**
   * 返回一个Promise
   * 根据传入参数产生以下情况
   * 1. 参数为Promise, 直接返回这个Promise
   * 2. 参数为PromiseLike, 使用resolve吸收PromiseLike, 状态和结果与PromiseLike一致
   * 3. 参数为其他, 直接resolve(值)
   * @param {any} data 
   * @returns 
   */
  static resolve(data) {
    if(data instanceof MyPromise) {
      return data
    }
    // 这里不推荐 使用 promise.#resolve吸收, 因为没有进行 resolvePromise 判断  
    const promise = new MyPromise((resolve) => {
      resolve(data)
    })
    return promise
  }

reject 实现

  /**
   * 返回一个拒绝的Promise
   * @param {any} data 
  */	
  static reject(reason) {
    const promise = new MyPromise((resolve, reject) => {
      reject(reason)
    })
    return promise
  }

all 和 allSettled 实现

all 实现

  • 根据传入参数产生以下情况
  1. 参数为不可迭代对象, Promise直接为拒绝状态, 结果为报错原因
  2. 可迭代对象为空, Promise直接为完成状态, 结果为空数组
  3. 可迭代对象中, 所有的Promise都为完成状态后, Promis状态为完成, 结果为按照迭代对象顺序排列的数组
  4. 可迭代对象中, 只要有一个Promise为拒绝状态, Promise状态为拒绝, 结果为最先拒绝的Promise结果
  
  /**
   * 返回一个Promise
   * 根据传入参数产生以下情况
   * 1. 参数为不可迭代对象, Promise直接为拒绝状态, 结果为报错原因
   * 2. 可迭代对象为空, Promise直接为完成状态, 结果为空数组
   * 3. 可迭代对象中, 所有的Promise都为完成状态后, Promis状态为完成, 结果为按照迭代对象顺序排列的数组
   * 4. 可迭代对象中, 只要有一个Promise为拒绝状态, Promise状态为拒绝, 结果为最先拒绝的Promise结果
   * @param {Iterator} iterator 
   * @returns 
   */
  static all(iterator) {
    return new MyPromise((resolve, reject) => {
      const result = [] // 汇总结果
      let count = 0 // 总数量
      let finishCount = 0 // 完成数量
      try {
        for (const pros of iterator) {
          // 当前索引
          const currentIndex = count++
          MyPromise.resolve(pros).then((data) => {
            result[currentIndex] = data
            finishCount++
            // 完成数量 与 总数量相等
            if(finishCount === count) resolve(result)
          }, reject)
        }
      } catch (error) {
        console.error(error)
        reject(error)
        return
      }
      // 迭代对象为空时
      if(!count) resolve(result)
    })
  }

allSettled 实现

  • 根据传入参数产生以下情况
  1. 参数为不可迭代对象, Promise直接为拒绝状态, 结果为错误原因
  2. 可迭代对象为空, Promise直接为完成状态, 结果为空数组
  3. 可迭代对象中, 所有Promise状态都为已决时, Promise状态为完成, 结果为按照迭代对象顺序排列的数组(每一项中有对应的状态和结果)
  
  /**
   * 返回一个Promise
   * 根据传入参数产生以下情况
   * 1. 参数为不可迭代对象, Promise直接为拒绝状态, 结果为错误原因
   * 2. 可迭代对象为空, Promise直接为完成状态, 结果为空数组
   * 3. 可迭代对象中, 所有Promise状态都为已决时, Promise状态为完成, 结果为按照迭代对象顺序排列的数组(每一项中有对应的状态和结果)
   * @param {Iterator} iterator 
   * @returns 
   */
  static allSettled(iterator) {
    const result = []
    try {
      for (const pros of iterator) {
        result.push(MyPromise.resolve(pros).then(data => ({
          status: FULFILLED,
          value: data
        }), reason => ({
          status: REJECTED,
          reason
        })))
      }
    } catch (error) {
      return MyPromise.reject(error)
    }
    return MyPromise.all(result)
  }

race 实现

  • 根据参数产生以下情况
  1. 参数为不可迭代对象, Promise直接为拒绝状态, 结果为报错原因
  2. 可迭代对象为空, Promise保持挂起状态
  3. 可迭代对象中, 哪个Promise状态先变为已决, Promise状态和结果与其一致
  /**
   * 返回一个Promise
   * 根据参数产生以下情况
   * 1. 参数为不可迭代对象, Promise直接为拒绝状态, 结果为报错原因
   * 2. 可迭代对象为空, Promise保持挂起状态
   * 3. 可迭代对象中, 哪个Promise状态先变为已决, Promise状态和结果与其一致
   * @param {Iterator} iterator 
   * @returns 
   */
  static race(iterator) {
    return new MyPromise((resolve, reject) => {
      try {
        for (const pros of iterator) {
          MyPromise.resolve(pros).then(resolve, reject)
        }
      } catch (error) {
        console.error(error)
        reject(error)
      }
    })
  }

any 实现

  • 根据参数产生以下情况
  1. 参数为不可迭代对象, Promise直接为拒绝状态, 结果为报错原因
  2. 可迭代对象为空, Promise直接为拒绝状态, 结果是一个AggregateError错误对象(对象的Errors为空数组)
  3. 可迭代对象中, 哪个Promise状态先为成功时, Promise的状态和结果与其一致
  4. 可迭代对象中, 所有Promise状态都为拒绝时, Promise的状态为拒绝, 结果是AggregateError错误对象(对象的Errors为按照迭代对象顺序排列的数组)
 /**
   * 返回一个Promise
   * 根据参数产生以下情况
   * 1. 参数为不可迭代对象, Promise直接为拒绝状态, 结果为报错原因
   * 2. 可迭代对象为空, Promise直接为拒绝状态, 结果是一个AggregateError错误对象(对象的Errors为空数组)
   * 3. 可迭代对象中, 哪个Promise状态先为成功时, Promise的状态和结果与其一致
   * 4. 可迭代对象中, 所有Promise状态都为拒绝时, Promise的状态为拒绝, 结果是AggregateError错误对象(对象的Errors为按照迭代对象顺序排列的数组)
   * @param {Iterator} iterator 
   * @returns 
   */
  static any(iterator) {
    return new MyPromise((resolve, reject) => {
      let count = 0 // 总数
      let errorCount = 0 // 失败数量
      const errorResult = [] // 失败汇总结果
      try {
        for (const pros of iterator) {
          const currentIndex = count++
          MyPromise.resolve(pros).then(resolve, (reason) => {
            errorCount++
            errorResult[currentIndex] = reason
            if(count === errorCount) reject(new AggregateError(errorResult, 'All promises were rejected'))
          })
        }
      } catch (error) {
        console.error(error)
        reject(error)
        return
      }
      // 迭代对象为空时
      if(!count) reject(new AggregateError(errorResult, 'All promises were rejected'))
    })
  }

withResolvers 实现

  • 返回一个对象 包含一个新的 Promise 对象和两个函数
  /**
   * 返回一个对象 包含一个新的 Promise 对象和两个函数
   * @returns 
   */
  static withResolvers() {
    let resolve, reject
    const promise = new MyPromise((a, b) => {
      resolve = a
      reject = b
    })
    return {
      promise,
      resolve,
      reject
    }
  }