返回由异步函数循环填充的数组

Mat*_*att 4 javascript asynchronous node.js

我认为这是一个相当简单的问题,但我主要使用 ruby​​ 进行编程,并且我在 javascript 中的异步函数上遇到了麻烦。具体来说,我有一个方法,应该用从 API 异步获取的结果填充数组。我能够得到很好的结果,但在填充数组后我似乎无法返回该数组。相反,return 语句在 Promise 解决之前执行,因此返回一个空数组。简化的代码示例如下:

async function getAnimalSounds(animals){
   var sounds = []
   for (const a of animals){
     asynchronously_fetch_sound(a).then((result) => {
       sounds.push(result)
     })
   }
   
   return sounds // sounds returns as an empty array
}
Run Code Online (Sandbox Code Playgroud)

先感谢您!

小智 8

这里的问题是您正在使用普通for循环来遍历animals数组。NodeJS 中的循环不会等待当前迭代的 Promise 解决后再进入下一个迭代,因此循环将在您解决 Promise 之前完成。

最好的办法是构造一个要解决的 Promise 数组,然后调用Promise.all该数组。

async function getAnimalSounds(animals){
    const promises = animals.map(a => asynchronously_fetch_sound(a))
    const sounds = await Promise.all(promises)

    return sounds
}

Run Code Online (Sandbox Code Playgroud)

或者,如果您乐意使用 Bluebird 库(此处的文档),您可以执行以下操作:

const Bluebird = require('bluebird') // import Bluebird library

async function getAnimalSounds(animals){
    const sounds = await Bluebird.map(animals, (a) => asynchronously_fetch_sound(a))

    return sounds
}
Run Code Online (Sandbox Code Playgroud)

请记住,由于您已经编写了异步函数,因此在对其输出执行任何操作之前,您需要等待它解析;通过awaiting 它或通过调用.then(...).