javascript如何使用async并行等待循环内部



我在express js和mongoose中有下一个例子。学生与省份之间存在关系:

app.get('/example', async (req, res) => {
const provinces = await Province.find();
let studentsByProvince = [];
for (let prov of provinces) {
const st = await Student.count({ province: prov });
studentsByProvince.push({ province: prov.province, totalStudents: st });
}
res.json(studentsByProvince);});

这是无效的,因为在循环内搜索是按顺序执行的。我是这样解决的:

app.get('/example2', async (req, res) => {
const provinces = await Province.find();
let studentsByProvince = [];
let studentsByProvincePromises = [];
for (let prov of provinces) {
const studentPromise = Student.count({ province: prov });
studentsByProvincePromises.push(studentPromise);
}
const studentsByProvinceResult = await Promise.all(studentsByProvincePromises);
for (let [index, prov] of provinces.entries()) {
studentsByProvince.push({ province: prov.province, totalStudents: studentsByProvinceResult[index] });
}
res.json(studentsByProvince);});

我已经解决了并行执行它的问题,但是我必须经历两次循环,因为查询返回的是promise而不是结果。有一些异步等待的方法来解决这个例子,类似于第一种方法,但是并行的。

您可以在第一个循环中为promise附加回调:

app.get('/example2', async (req, res) => {
const provinces = await Province.find();
let studentsByProvincePromises = [];
for (let prov of provinces) {
const studentPromise = Student.count({ province: prov })
.then(st => ({ province: prov.province, totalStudents: st });
studentsByProvincePromises.push(studentPromise);
}
const studentsByProvince = await Promise.all(studentsByProvincePromises);
res.json(studentsByProvince);
});

使用Array.prototype.map将使内容看起来更简洁:

app.get('/example2', async (req, res) => {
const provinces = await Province.find();
const studentsByProvince = await Promise.all(
provinces.map(prov => {
return (Student.count({ province: prov })
.then(totalStudents => ({ province: prov.province, totalStudents })
)
})
);
res.json(studentsByProvince);
});

我认为您可以以不同的方式实现这一点,甚至可以保存数据库查询。既然你无论如何都想要所有省份(你也可以通过编程向管道添加一个过滤器(,为什么不进行聚合呢?

Student.aggregate([
{
$group:{
_id: "$province", // this is the property we are grouping by 
count: { $sum: 1 }
}   
}
])

这将返回具有以下结构的对象数组:

[
{
"_id" : "provinceName",
"count" : 6
},
....
]

最新更新