【JavaScript】手写 Promise(静态方法)

手写Promise-静态方法resolve

需求:

  1. 返回一个带有成功原因的Promise对象
HMPromise.resolve(new HMPromise((resolve, reject) => {
  // resolve('resolve')
  // reject('reject')
  // throw 'error'
})).then(res => {
  console.log('res:', res)
}, err => {
  console.log('err:', err)
})
HMPromise.resolve('itheima').then(res => {
  console.log(res)
})


核心步骤:

  1. 增加静态方法resolve,根据传入的值返回不同的结果即可
  static resolve(value) {
    // 1. 判断传入值
    if (value instanceof HMPromise) {
      // 2.1 Promise直接返回
      return value
    }
    // 2.2 转为Promise并返回(fulfilled状态)
    // return new HMPromise((resolve, reject) => {
    return new HMPromise((resolve) => {
      resolve(value)
    })
  }
面试回答:

手写Promise-静态方法resolve

  1. 通过static关键字添加静态方法resolve,接收参数value
  2. 内部判断传入的值
    1. 如果是Promise实例,直接返回
    2. 其他的值,创建Promise实例并返回,内部通过resolve(value)传递value

手写Promise-静态方法reject

需求:

  1. 返回一个带有拒绝原因的Promise对象
HMPromise.reject('error').catch(res => {
  console.log(res)
})

核心步骤:

  1. 添加静态方法
  2. 返回rejected状态的Promise
  static reject(value) {
    // 1. 返回rejected状态的Promise
    // new HMPromise((resolve,reject)=>{
    return new HMPromise((undefined, reject) => {
      reject(value)
    })
  }
面试回答

手写Promise-静态方法reject

  1. 添加静态方法reject并接收参数value
  2. 内部返回一个拒绝状态的Promise实例即可

手写Promise-静态方法race

需求:

  1. 接收Promise数组,数组中第一个Promise敲定时,获取成功/失败结果
  2. 传入的参数不是数组,直接报错

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

const p1 = new HMPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 2000)
})
const p2 = new HMPromise((resolve, reject) => {
  setTimeout(() => {
    reject(2)
  }, 1000)
})
HMPromise.race([p1, p2, 'itheima']).then((res) => {
  console.log('res:', res)
}, err => {
  console.log('err:', err)
})

核心步骤:

  1. 返回Promise
  2. 判断是否未数组,不是直接报错
  3. 等待第一个敲定
  static race(promises) {
    // 1. 返回Promise
    return new HMPromise((resolve, reject) => {
      // 2. 判断是否为数组
      if (!Array.isArray(promises)) {
        return reject(new TypeError('Argument is not iterable'))
      }
      // 3. 等待第一个敲定
      promises.forEach(p => {
        // p.then
        HMPromise.resolve(p).then(res => { resolve(res) }, err => { reject(err) })
      })
    })
  }
面试回答:

手写Promise-静态方法race

  1. 添加静态方法race接收参数promises
  2. 内部返回一个新的Promise实例,在返回的Promise实例中:
    1. 判断参数是否为数组,不是通过reject传递错误
    2. 遍历Promise数组,通过resolve静态方法等待每一个兑现
    3. 任何一个兑现,调用resolve传递兑现结果
    4. 任何一个拒绝,调用reject传递拒绝原因

手写Promise-静态方法all

需求:

  1. 接收Promise数组
    1. 所有Promise都成功时,返回一个成功的Promise对象及成功数组
    2. 任何一个Promise失败,返回一个失败的Promise对象及第一个失败原因
const p1 = HMPromise.resolve(1)
const p2 = new HMPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(2)
    // reject('error')
  }, 1000)
})
const p3 = 3
HMPromise.all([p1, p2, p3]).then(res => {
  console.log('res:', res)
}, err => {
  console.log('err:', err)
})

核心步骤:

  1. 返回Promise
  2. 判断参数是否未数组:
    1. 不是:直接报错
  3. 是:
    1. 空数组直接兑现
  4. 处理全部兑现:记录结果->判断全部兑现
    1. 处理第一个拒绝
static all(promises) {
    // 1. 返回Promise实例
    return new HMPromise((resolve, reject) => {
      // 2. 判断是否为数组
      if (!Array.isArray(promises)) {
        return reject(new TypeError('Argument is not iterable'))
      }
      // 3. 空数组直接兑现
      promises.length === 0 && resolve(promises)
      // 4.1 记录结果
      const results = []
      let count = 0
      promises.forEach((p, index) => {
        HMPromise.resolve(p).then(res => {
          // results.push 无法保证 结果的顺序和Promise数组的顺序一致
          // index 和 Promise实例的索引一致,保证顺序
          results[index] = res
          // 4.2 判断全部兑现
          count++
          count === promises.length && resolve(results)
        }, err => {
          // 5. 处理第一个拒绝
          reject(err)
        })
      })
    })
  }

面试回答:

手写Promise-静态方法all

  1. 添加静态方法all
  2. 内部返回Promise实例,在返回的Promise实例中:
    1. 判断参数是否为数组,不是通过reject传递错误
    2. 空数组直接以空数组为结果进行兑现
    3. 遍历Promise数组,通过resolve静态方法等待结果
      1. 处理全部兑现:
        1. 通过数组记录结果,用索引的方式来添加,目的是保证结果的顺序和Promise数组的顺序一致
        2. 通过兑现次数进行判断,因为是通过索引的方式记录结果,如果第一次兑现的是最后一个,那么数组的长度就已经和Promise数组的长度一致了,所以需要通过兑现次数来进行判断
      2. 任意一个拒绝,调用reject传递拒绝原因

手写Promise-静态方法allSettled

需求:-传送门

  1. 传入Promise数组,当所有对象都已敲定时
  2. 返回一个新的Promise对象及以数组形式保存的结果
const p1 = HMPromise.resolve(1)
const p2 = 2
const p3 = new HMPromise((resolve, reject) => {
  setTimeout(() => {
    reject(3)
  }, 1000)
})
HMPromise.allSettled([p1, p2, p3]).then(res => {
  console.log('res:', res)
}, err => {
  console.log('err:', err)
})

核心步骤:

  1. 返回Promise
  2. 判断是否为数组:
    1. 不是:报错
    2. 是:
      1. 空数组:直接兑现
      2. 等待全部敲定:并记录结果
        1. 处理兑现:{state:FULFILLED,value:'xxx'}
        2. 处理拒绝:{state:REJECTED,reason:'xxx'}
  static allSettled(promises) {
    // 1. 返回Promise
    return new HMPromise((resolve, reject) => {
      // 2. 数组判断
      if (!Array.isArray(promises)) {
        return reject(new TypeError('Argument is not iterable'))
      }
      // 3. 为空直接敲定
      promises.length === 0 && resolve(promises)

      // 4. 等待全部敲定
      // 4.1 记录结果
      const results = []
      let count = 0
      promises.forEach((p, index) => {
        HMPromise.resolve(p).then(res => {
          // 4.2 处理兑现{status:'fulfilled',value:''}
          results[index] = { status: FULFILLED, value: res }
          count++
          count === promises.length && resolve(results)
        }, err => {
          // 4.3 处理拒绝{status:'rejected',reason:''}
          results[index] = { status: REJECTED, reason: err }
          count++
          count === promises.length && resolve(results)
        })
      })
    })
  }


面试回答:

手写Promise-静态方法allSettled

做法和all方法类似,区别是要获取全部敲定的结果(成功/拒绝),以及获取的结果是对象形式

  1. 添加静态方法allSettled
  2. 内部返回Promise实例,在返回的Promise实例中:
    1. 判断参数是否为数组,不是通过reject传递错误
    2. 空数组直接以空数组为结果进行兑现
  3. 遍历Promise数组,通过resolve静态方法等待敲定结果
  4. 等待全部敲定:并记录结果,根据兑现和拒绝将如下格式的内容通过索引的方式的记录到数组中
    1. 处理兑现:{state:FULFILLED,value:'xxx'}
    2. 处理拒绝:{state:REJECTED,reason:'xxx'}
  5. 根据敲定的次数判断是否全部敲定,全部敲定之后,通过resolve传递结果数组

手写Promise-静态方法any

需求:-传送门

  1. 传入Promise数组,
    1. 任何一个Promise对象敲定时,返回一个新的Promise对象,及对应的结果
    2. 所有Promise都被拒绝时,返回一个包含所有拒绝原因的AggregateError错误数组
const p1 = new HMPromise((resolve, reject) => {
  setTimeout(() => {
    reject(1)
  }, 2000)
})
const p2 = 2
const p3 = new HMPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(3)
    // reject(3)
  }, 1000)
})
HMPromise.any([p1, p2, p3]).then(res => {
  console.log('res:', res)
}, err => {
  console.dir(err)
})

核心步骤:

  1. 返回Promise
  2. 判断是否为数组
    1. 不是:报错
    2. 是:
      1. 空数组:直接拒绝
      2. 等待结果:
        1. 第一个兑现
        2. 全部拒绝
  static any(promises) {
    // 1. 返回Promise,数组判断
    return new HMPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        return reject(new TypeError('Argument is not iterable'))
      }
      // 2. 空数组直接拒绝
      promises.length === 0 && reject(new AggregateError(promises, 'All promises were rejected'))

      // 3. 等待结果
      const errors = []
      let count = 0
      promises.forEach((p, index) => {
        HMPromise.resolve(p).then(res => {
          // 3.1 第一个兑现
          resolve(res)
        }, err => {
          // 3.2 全部拒绝
          errors[index] = err
          count++
          count === promises.length && reject(new AggregateError(errors, 'All promises were rejected'))
        })
      })
    })
  }


面试回答:

手写Promise-静态方法any

做法和all方法也有点类似,区别是获取第一个兑现,或者是全部拒绝

  1. 添加静态方法any
  2. 内部返回Promise实例,在返回的Promise实例中:
    1. 判断参数是否为数组,不是通过reject传递错误
    2. 空数组直接以空数组为结果进行兑现
  3. 遍历Promise数组,通过resolve静态方法等待结果
    1. 第一个兑现,通过resolve传递兑现结果
    2. 全部拒绝:
      1. 定义数组,保存拒绝原因,通过索引记录,目的是保证顺序和Promise数组一致
      2. 通过次数判断是否全部拒绝,当全部拒绝时,通过reject传递AggregateError类型的错误,并将拒绝原因数组传递进去即可
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秀秀_heo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值