我正在为浏览器中触发的特定GET请求开发一个简单的函数。此请求的目的是对 mongodb(猫鼬(数据库进行多次查询,然后对结果执行一些计算和结构格式化,以将其发送回浏览器。 唯一的问题是一切都花费太长时间,并导致浏览器中出现错误:
网::ERR_EMPTY_RESPONSE
举一个我试图在这里构建的部分函数的示例,它是这样的:
async function getPriceByMake(makes, id) {
return new Promise(async (resolve, reject) => {
let pMakes = {};
const makesArr = Object.keys(makes);
for (let i = 0; i < makesArr.length; i++) {
console.log('Getting the docs ... ' + Math.round(i/makesArr.length*100) + '%')
const currMake = makesArr[i];
pMakes[currMake] = {};
const modelsArr = Object.keys(makes[currMake]);
for (let j = 0; j < modelsArr.length; j++) {
const currModel = modelsArr[j];
await Listing.find({ catFrom: id, model: currModel }, 'year asking', (err, docs) => {
if (docs.length > 1) {
pMakes[currMake][currModel] = [docs];
} else {
pMakes[currMake][currModel] = {};
}
});
}
}
resolve(pMakes);
});
}
在这个函数中,如果我省略async / await
,我会在另一端得到一个空{}
。这显然不是目标。
我一直在网上搜索了一下,能够找到一篇指向这个方案的文章:
浏览器:
- 发起请求
- 显示进度
- 显示结果
网络服务器:
- 提交事件
- 检查完成情况
- 返回结果
后端应用:
- 提货事件
- 运行任务
- 返回结果
我的问题如下:如何使用 NodeJS 和 Express 做到这一点?
在此代码中:
for (let j = 0; j < modelsArr.length; j++) {
const currModel = modelsArr[j];
await Listing.find({ catFrom: id, model: currModel }, 'year asking', (err, docs) => {
if (docs.length > 1) {
pMakes[currMake][currModel] = [docs];
} else {
pMakes[currMake][currModel] = {};
}
});
}
您的await
不起作用,因为您正在向Listing.find()
传递回调。 当你这样做时,它不会返回承诺,因此await
不会做任何有用的事情。 您得到空响应是因为await
不起作用,因此您在没有任何实际数据之前调用resolve()
。
将代码更改为以下内容:
for (let j = 0; j < modelsArr.length; j++) {
const currModel = modelsArr[j];
let docs = await Listing.find({ catFrom: id, model: currModel }, 'year asking');
if (docs.length > 1) {
pMakes[currMake][currModel] = [docs];
} else {
pMakes[currMake][currModel] = {};
}
}
然后,await
将正常工作。
您还应该删除return new Promise()
包装器。 你不想要那个。 只需使函数async
并使用await
,它就会返回一个承诺。
这是删除了不必要的 promise 包装器的函数:
async function getPriceByMake(makes, id) {
let pMakes = {};
const makesArr = Object.keys(makes);
for (let i = 0; i < makesArr.length; i++) {
console.log('Getting the docs ... ' + Math.round(i/makesArr.length*100) + '%')
const currMake = makesArr[i];
pMakes[currMake] = {};
const modelsArr = Object.keys(makes[currMake]);
for (let j = 0; j < modelsArr.length; j++) {
const currModel = modelsArr[j];
let docs = await Listing.find({ catFrom: id, model: currModel }, 'year asking');
if (docs.length > 1) {
pMakes[currMake][currModel] = [docs];
} else {
pMakes[currMake][currModel] = {};
}
}
}
return pMakes;
}
然后,请记住,无论发送实际响应的任何代码,在调用此async
函数时都需要使用.then()
或await
才能获得最终结果。
加快此代码的最佳方法是重构查询和/或数据库结构,这样就不必执行 N * M 个单独的查询来获得最终结果。 这可能就是你的缓慢的来源。 最大的性能提升可能来自将必须在此处运行的查询数量减少到更少。
根据您的数据库配置和功能,并行运行内部循环查询可能会加快速度,如下所示:
async function getPriceByMake(makes, id) {
let pMakes = {};
const makesArr = Object.keys(makes);
for (let i = 0; i < makesArr.length; i++) {
console.log('Getting the docs ... ' + Math.round(i/makesArr.length*100) + '%')
const currMake = makesArr[i];
pMakes[currMake] = {};
const modelsArr = Object.keys(makes[currMake]);
await Promise.all(modelsArr.map(async currModel => {
let docs = await Listing.find({ catFrom: id, model: currModel }, 'year asking');
if (docs.length > 1) {
pMakes[currMake][currModel] = [docs];
} else {
pMakes[currMake][currModel] = {};
}
}));
}
return pMakes;
}