Javascript 异步/等待:使用array.prototype.map(工作)与array.prototype.filter(不工作)进行异步数组转换

Javascript 异步/等待:使用array.prototype.map(工作)与array.prototype.filter(不工作)进行异步数组转换,javascript,node.js,asynchronous,async-await,Javascript,Node.js,Asynchronous,Async Await,我几乎可以肯定这是有原因的,但我刚刚花了一个多小时试图弄清楚为什么我的异步代码在尝试使用ari.filter()转换数组时很早就解决了问题,但在使用ari.map()时,异步代码会在我预期的时间内解决问题。任何人谁可以帮助阐明这一主题将不胜感激 为了清晰起见,我还使用了节点8.2.1 因此,为了提供一些代码和输出来描述这个问题,下面是一个使用ari.map的示例,它工作,并在控制台中提供以下输出 (async () => { const timeStart = Date.now()

我几乎可以肯定这是有原因的,但我刚刚花了一个多小时试图弄清楚为什么我的异步代码在尝试使用
ari.filter()
转换数组时很早就解决了问题,但在使用
ari.map()
时,异步代码会在我预期的时间内解决问题。任何人谁可以帮助阐明这一主题将不胜感激

为了清晰起见,我还使用了节点8.2.1

因此,为了提供一些代码和输出来描述这个问题,下面是一个使用
ari.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
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
因此,正如您所期望的,从原始数组被转换到输出结果与预期结果之间大约有1秒钟的时间

(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')
})()
下面的代码非常相似,但是使用了
ari.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')
})()
在使用async/await时,为什么
ary.filter()
在转换数组和在适当的时间解析方面与
ary.map()
的行为不一样?

调用
Promise.all()
仅在Promise数组上才有意义

.map()
返回其回调的结果,如果回调是异步的,则返回结果是一个承诺。因此,这很好

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

调用
Promise.all()
仅对promises数组有意义

.map()
返回其回调的结果,如果回调是异步的,则返回结果是一个承诺。因此,这很好


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

啊,谢谢,我想我明白了,但只是确认一下,因为在我的示例中,我返回了对
.filter()
的承诺,这总是真实的,我将获得原始数组的所有元素?我假设除了bluebird中肯定存在的一些实用程序(如果可能的话,尝试使用本机承诺)或者通过编写几行额外的代码来使用之外,没有其他解决方法。map以某种方式返回true/false,然后在该数组上过滤?@LanceWhatley:正确。再次感谢,由于时间不够,无法接受您的答案,但很快就会接受。啊,谢谢,我想我明白了,但只是确认一下,因为在我的示例中,我向
.filter()
,返回了一个承诺,这始终是真实的,我将获得原始数组的所有元素?我假设除了bluebird中肯定存在的一些实用程序(如果可能的话,尝试使用本机承诺)或者通过编写几行额外的代码来使用之外,没有其他解决方法。map以某种方式返回true/false,然后在该数组上过滤?@LanceWhatley:正确。再次感谢,由于时间不够,目前无法接受您的答案,但很快会接受。