如何使用 Express 处理长请求



我正在为浏览器中触发的特定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;
}

最新更新