我认为这是一个相当简单的问题,但是我主要是用ruby和ma编程的,很难理解JavaScript中的异步函数。具体地说,我有一个方法,它应该用从API异步获取的结果填充数组。我能够得到很好的结果,但我似乎无法返回数组之后,它已经被填充。相反,return语句在承诺被解析之前执行,因此返回一个空数组。下面的简化代码示例:
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
}
提前谢谢你!
由于您已经使用了async-await
语法,因此不需要使用promise-chaining。只需使用await
关键字来等待承诺的解决。
async function getAnimalSounds(animals){
var sounds = []
for (const a of animals) {
const res = await asynchronously_fetch_sound(a);
sounds.push(res);
}
return sounds
}
注意:以上代码将进行顺序异步请求。您可以使用promise.all()
发出并行请求。
async function getAnimalSounds(animals){
var sounds = await Promise.all(
animals.map((a) => asynchronously_fetch_sound(a))
);
return sounds;
}
这里的问题是您正在使用一个普通的for
循环来遍历动物
数组。NodeJS中的循环不会等待当前迭代的承诺得到解决后再进行下一个迭代,因此循环将在您解决承诺之前完成。
最好的做法是构造一个要解析的承诺数组,然后在该数组上调用promise.all
。
async function getAnimalSounds(animals){
const promises = animals.map(a => asynchronously_fetch_sound(a))
const sounds = await Promise.all(promises)
return sounds
}
或者,如果您愿意使用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
}
记住,由于您已经编写了一个异步函数,因此在对其输出执行任何操作之前,您将需要等待它解析;通过等待
或调用。然后(。。。)
。
您应该为异步方法调用添加await
。
async function getAnimalSounds(animals){
var sounds = []
for (const a of animals){
const result = await asynchronously_fetch_sound(a);
sounds.push(result)
}
return sounds // sounds returns as an empty array
}
但是,最佳实践是使用promise.all()
async function getAnimalSounds(animals){
var sounds = []
const promises = []
for (const a of animals){
promises.push(asynchronously_fetch_sound(a));
}
sounds = await Promise.all(promises);
return sounds;
}