【问题标题】:async / await: asynchronous array transformation using Array.prototype.map (works) vs Array.prototype.filter (not working)async / await:使用 Array.prototype.map(有效)与 Array.prototype.filter(无效)的异步数组转换
【发布时间】:2017-08-04 03:29:14
【问题描述】:

我几乎肯定必须对此进行解释,但我只花了一个多小时试图弄清楚为什么我的异步代码在尝试使用 ary.filter() 转换数组时似乎提前解决了,但是当使用ary.map() async 可以在我期望的时候解决。任何可以帮助阐明这个主题的人将不胜感激!

为了清楚起见,我也使用节点 8.2.1。

因此,为了提供一些代码和输出来描述问题,这里是一个使用ary.map 的示例,它有效,并在控制台中提供以下输出。

(async () => {
  const timeStart = Date.now()
  const ary = new Array(20).fill(0).map((v, i) => i+1)

  const newAry = await Promise.all(
    ary.map(async val => {
      return await new Promise((resolve, reject) => {
        setTimeout(() => resolve(val*2), 1000)
      })
    })
  )
  console.log('original ary', ary)
  console.log('newAry is', newAry)
  const timeEnd = Date.now()
  console.log(timeEnd - timeStart, 'milliseconds between start and end')
})()

到控制台的输出如下:

original ary [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ]
newAry is [ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40 ]
1022 milliseconds between start and end

正如您所料,在转换原始数组和输出符合预期之间有约 1 秒的时间。

以下代码非常相似,但使用了ary.filter(),并且按预期返回。

(async () => {
  const timeStart = Date.now()
  const ary = new Array(20).fill(0).map((v, i) => i+1)

  const newAry = await Promise.all(
    ary.filter(async val => {
      return await new Promise((resolve, reject) => {
        setTimeout(() => resolve(Math.random() < 0.5), 1000)
      })
    })
  )
  console.log('original ary', ary)
  console.log('newAry is', newAry)
  const timeEnd = Date.now()
  console.log(timeEnd - timeStart, 'milliseconds between start and end')
})()

输出如下:

original ary [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ]
newAry is [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ]
18 milliseconds between start and end

为什么ary.filter() 在使用 async/await 时在转换数组和在适当的时间解析方面的行为与 ary.map() 不同?

【问题讨论】:

    标签: javascript node.js asynchronous async-await


    【解决方案1】:

    调用Promise.all() 仅对一组承诺有意义。

    .map() 返回其回调的结果,如果回调是异步的,则它是一个承诺。因此,这工作正常。

    .filter() 将其回调的结果视为布尔值(它不是),然后返回原始数组中的项目。

    【讨论】:

    • 啊,谢谢,我想我明白了,但只是为了确认一下,因为在我的示例中,我向.filter() 返回了一个承诺,这始终是真实的,我将获得原始数组的所有元素?我假设除了一些我确定存在于 bluebird 中的实用程序(如果可能的话,尝试使用本机承诺)或通过编写几行额外的代码来使用 .map 以某种方式返回 true/false 之外,没有其他解决方法然后过滤那个数组?
    • @LanceWhatley:正确。
    • 再次感谢,由于时间不够,无法接受您的回答,但很快就会接受。
    猜你喜欢
    • 1970-01-01
    • 2018-05-10
    • 2018-06-04
    • 2021-11-04
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    • 2018-09-01
    相关资源
    最近更新 更多