Promise 静态方法实现

吐槽君 分类:javascript

原文地址

概述

6 个静态方法的一些注意点罗列如下:

  • 除了 resolve reject 其它静态方法的参数都要求传递一个可迭代对象(iterable),而可迭代对象具有 Symbol.iterator 属性定义生成器(执行生成器生成迭代器),通过判断实参 Symbol.iterator 是否为函数作防御性检测
  • try...catch 把未传参数或者传 undefined 错误信息通过 reject 传递出去
  • 静态方法都返回 promise,所以基本思路是返回一个 Promise 实例,再根据接口的各自用途实现内部逻辑
  • iterable 对象中每一项同时执行(当然还是顺序执行,但不必等待其它项的执行结果)
  • 由于 iterable 对象中的每一项不必是 Promise 实例,那么使用 Promise.resolve 包一下强制生成 Promise 实例
  • 多条 promise 链,同样位置的回调同属一个微任务队列,链条后面同样位置的回调同属于后面的微任务队列,如下:
Promise.reject(1).catch(r=>console.log(r))
Promise.reject(2).then(r=>console.log(r)).catch(e=>console.log('e',e))
Promise.resolve(3).then(r=>console.log(r)).then(_=>console.log('then'))
// 1
// 3
// e 2
// then
 

Promise.resolve

快速生成一个 fulfilled promise 对象

Promise._resolve = value => new Promise(resolve => resolve(value))
 

Promise.reject

快速生成一个 rejected promise 对象

Promise._reject = value => new Promise((_, reject) => reject(value))
 

Promise.all

iterable 对象只要有一项的状态是 rejected 返回的 promise 状态为 rejected,否则为 fulfilled,fulfilled 的数组每一项顺序与实参一致

Promise._all = (array) => {
  return new Promise((resolve, reject) => {
    try {
      if (typeof array[Symbol.iterator] !== 'function')
        return reject(
          new TypeError(
            `${typeof array} ${array} is not iterable (cannot read property Symbol(Symbol.iterator))`
          )
        )
      array = [...array[Symbol.iterator]()]
      const result = []
      let length = array.length

      array.forEach((item, i) =>
        Promise.resolve(item).then((data) => {
          result[i] = data
          --length === 0 && resolve(result)
        }, reject)
      )
    } catch (e) {
      reject(e)
    }
  })
}

 

Promise.allSettled

返回的 promise 状态一定 fulfilled,其中每一项的状态与数据通过传递给成功回调的对象描述,结构为 [{status: 'fulfilled', value: 1}, {status: 'rejected', reason: 'something went wrong'] ,顺序与实参一致

Promise._allSettled = (array) => {
  return new Promise((resolve, reject) => {
    try {
      if (typeof array[Symbol.iterator] !== 'function')
        reject(
          new TypeError(
            `${typeof array} ${array} is not iterable (cannot read property Symbol(Symbol.iterator))`
          )
        )
      array = [...array[Symbol.iterator]()]
      const result = []
      let length = array.length

      array.forEach((item, i) =>
        Promise.resolve(item).then(
          (value) => {
            result[i] = {
              status: 'fulfilled',
              value,
            }
            --length === 0 && resolve(result)
          },
          (e) => {
            result[i] = {
              status: 'rejected',
              reason: e,
            }
            --length === 0 && resolve(result)
          }
        )
      )
    } catch (e) {
      reject(e)
    }
  })
}
 

Promise.any

Promise.all 相反,只要有一项状态为 fulfilled 返回 promise 状态为 fulfilled,否则为 rejected

Promise._any = (array) => {
  return new Promise((resolve, reject) => {
    try {
      if (typeof array[Symbol.iterator] !== 'function')
        reject(
          new TypeError(
            `${typeof array} ${array} is not iterable (cannot read property Symbol(Symbol.iterator))`
          )
        )
      array = [...array[Symbol.iterator]()]
      const result = []
      let length = array.length

      array.forEach((item, i) =>
        Promise.resolve(item).then(resolve, (e) => {
          --length === 0 &&
            reject(`AggretatedError: All promises were rejected`)
        })
      )
    } catch (e) {
      reject(e)
    }
  })
}

 

Promise.race

竞态,iterable 对象中状态先从 pending 转出的那一项成为返回 promise 的状态,并且把数据传递给成功/失败回调

Promise._race = (array) => {
  return new Promise((resolve, reject) => {
    try {
      if (typeof array[Symbol.iterator] !== 'function')
        reject(
          new TypeError(
            `${typeof array} ${array} is not iterable (cannot read property Symbol(Symbol.iterator))`
          )
        )
      array = [...array[Symbol.iterator]()]
      array.forEach((item) => Promise.resolve(item).then(resolve, reject))
    } catch (e) {
      reject(e)
    }
  })
}

 

回复

我来回复
  • 暂无回复内容