我有一个async
函数,需要返回一个user_ids数组。我的代码就像:
async function getUserIds(option) {
let user_ids = [];
if (option === 'test') {
const departments = await Departments.find({}).exec()
.catch(() => console.log('ERROR');
console.log('BEFORE LOOP');
await departments.forEach(async(dpt) => {
const pop = await Populations.findOne({_id: dpt.id})
.catch(() => console.log('ERROR');
console.log('work...');
if (pop && (pop.max > pop.min)) {
const _users = await User.find({_id: {$in: pop.ids}}).exec()
.catch(() => console.log("ERROR");
user_ids = user_ids.concat(_users.map((u) => u._id));
console.log('finished work...');
}
});
return user_ids;
}
async function main() {
let user_ids = await getUserIds('test');
console.log(user_ids);
}
现在,这总是返回一个空数组[]
,我可以以异步方式看到控制台日志:
BEFORE LOOP
[] --> the return
work...
work...
work...
work...
work...
work...
finished work...
finished work...
work...
finished work...
work...
finished work...
finished work...
我猜这行await departments.forEach(async(dpt) => {
并不是真的"awaiting"
,所以我该怎么办,我做错了什么?
答案 0 :(得分:2)
async
/ await
是使用Promise的一种糖方式。
async
就像new Promise()
,而await
就像.then()
。
使用Promise.all()
等到所有Promise的决心都解决后再继续。
在这种情况下,您应该使用Array.prototype.map()
而不是Array.prototype.forEach()。 forEach()
返回undefined
,您正在使用await
。 .map()
将返回一个Promise数组:
// Using .map()
departments = [ Promise, Promise, Promise ] // await till all Promise resolves to go foward.
// Using .forEach()
departments = 'undefined' // nothing to await for.
await Promise.all(
departments.map(async(dpt) => {
const pop = await Populations.findOne({_id: dpt.id})
.catch(() => console.log('ERROR');
console.log('work...');
if (pop && (pop.max > pop.min)) {
const _users = await User.find({_id: {$in: pop.ids}}).exec()
.catch(() => console.log("ERROR");
user_ids = user_ids.concat(_users.map((u) => u._id));
console.log('finished work...');
}
})
);
答案 1 :(得分:1)
在从函数返回结果之前,您应该等待部门的承诺。第forEach
行在您的情况下不起作用,请用map
或for of
以map
为例
...
const promises = departments.map(async(dpt) => {
const pop = await Populations.findOne({_id: dpt.id})
.catch(() => console.log('ERROR');
console.log('work...');
if (pop && (pop.max > pop.min)) {
const _users = await User.find({_id: {$in: pop.ids}}).exec()
.catch(() => console.log("ERROR");
user_ids = user_ids.concat(_users.map((u) => u._id));
console.log('finished work...');
}
});
await Promise.all(promises)
return user_ids