Skip to content

关于 myPromiseFully.js 中的一些问题 #1

@87YLu

Description

@87YLu

谢谢你的文章,受益匪浅😁。以下是我发现的一些问题:

[1] Promise.all

根据 mdn 文档,Promise.all() 方法接收一个 promise 的 iterable 类型。
Array.isArray 来判断感觉不是很对,用 iterable?.[Symbol.iterator] == null 或许会更合适一些。

在这个基础上,使用 length 来判断迭代的个数就会出现错误了。Set 跟 Map 是没有 length 属性的。
且也不能用 forEach 来遍历,因为如果传入 string 类型会报错。

这样写的话应该好一些:

Promise.all = function (iterable) {
  if (iterable?.[Symbol.iterator] == null) {
    throw new TypeError(
      `${iterable} is not iterable (cannot read property Symbol(Symbol.iterator))`,
    )
  }

  return new Promise((resolve, reject) => {
    let index = 0
    let count = 0
    const result = []
    const length =
      (iterable instanceof Set || iterable instanceof Map) ? iterable.size : iterable.length

    if (length === 0) {
      resolve([])
    }

    for (const item of iterable) {
      if (item instanceof Promise) {
        ;(index => {
          Promise.resolve(item).then(
            value => {
              result[index] = value
              count += 1
              count === length && resolve(result)
            },
            reason => {
              reject(reason)
            },
          )
        })(index)
      } else {
        result[index] = item
        count += 1
        count === length && resolve(result)
      }

      index += 1
    }
  })
}

同理,接收可迭代对象的 promise 方法都应该改一下参数校验的方式。


[2] Promise.resolve

当传入包含 then 方法的对象时,执行的顺序可能会与原生的 promise 有区别。比如

console.log(
  Promise.resolve({
    then() {
      console.log(1)
    },
  }),
)

以上代码,原生 promise 会先打印 promise,再打印 1,而手写的会先打印 1,再打印 promise。

且应该先判断 then 方法是否为一个函数。如果不是的话,会返回整个对象。


[3] Promise.any

errors.push(reason); 会导致 errors 数组的顺序不可控,与原生的 Promise.any 方法有出入。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions