node.js - Express.js 如何在数据库调用后从数组中获取数据?
问题描述
我正在尝试遍历我的数据库 obj 并将其推送到一个数组,以便我可以在一个 zip 中下载文件。问题是在循环之后“newarr”的响应是空的。
是因为在循环完成之前加载了响应吗?如果是这样,我怎样才能让它工作?
对 nodejs 和 async await 功能来说是全新的。
router.get('/customzip/:data', userMiddleware.isLoggedIn, (req, res) => {
const arr = JSON.parse(req.params.data);
const newarr = [];
arr.array.forEach( e => {
if(e.type === 'folder'){
db.query(`SELECT * FROM files fil JOIN folders f ON f.folder_id = fil.folder_id WHERE fil.folder_id = ${db.escape(e.id)}`, (err, obj) => {
if(err){
return res
.status(500)
.send({
msg: err
});
}
Object
.keys(obj)
.forEach( function (item, index) {
const path = obj[item].file_dir.toString();
const pseudoobj = {};
pseudoobj['path'] = path;
pseudoobj['name'] = obj[item].file_name + '.' + obj[item].file_type;
newarr.push(pseudoobj);
// res.zip(newarr, 'download_' + Date.now() + '.zip'); // returning array
});
// res.zip(newarr, 'download_' + Date.now() + '.zip'); // not returning array
});
}
});
res.zip(newarr, 'download_' + Date.now() + '.zip');
});
解决方案
我认为这可以解决问题
const asyncForEach = async (array, callback) => {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array)
}
}
router.get('/customzip/:data', userMiddleware.isLoggedIn, async (req, res) => {
try {
const arr = JSON.parse(req.params.data);
const newarr = [];
await asyncForEach(arr.array, await e => {
if (e.type === 'folder') {
const obj = await db.query(`SELECT * FROM files fil JOIN folders f ON f.folder_id = fil.folder_id WHERE fil.folder_id = ${db.escape(e.id)}`)
Object.keys(obj).map((item, index) => {
const path = obj[item].file_dir.toString();
const pseudoobj = {};
pseudoobj['path'] = path;
pseudoobj['name'] = obj[item].file_name + '.' + obj[item].file_type;
newarr.push(pseudoobj);
// res.zip(newarr, 'download_' + Date.now() + '.zip'); // returning array
});
// res.zip(newarr, 'download_' + Date.now() + '.zip'); // not returning array
}
})
// console.log the new array to make sure this is what you want
console.log(newarr)
res.status(200).zip(newarr, 'download_' + Date.now() + '.zip');
} catch (msg) {
res.status(500).send({ msg })
}
});
基本上,您正在循环您的数据库,这是一个异步操作。您正在将回调函数传递给数据库调用并执行代码,但由于它是一个异步函数,因此代码继续运行并返回一个空数组,因为它尚未完成运行。在 Promise 上使用 await 会告诉请求循环继续处理应用程序中的其他事情,并在 Promise 完成时再次在该位置拾取,然后恢复该功能的其余部分。
另外,因为您试图触发 MULTIPLE 异步调用,所以您希望在不阻塞请求循环的情况下同步循环它们,这就是我添加 asyncForEach 函数的原因
推荐阅读
- c - 无法从设备驱动程序创建的设备中读取
- javascript - 无法读取未定义的属性(读取“名称”)?
- node.js - RSocketTcpClient 不是构造函数 - 带有 Rsocket-js 的 NodeJS
- webpack - webpack-dev-server 看起来与 webpack 构建不同
- php - PHP - 允许将函数重新声明为包含来自另一个文件
- xslt - XSLT 分组和计算总数
- reactjs - .map 函数在页面上多次重新渲染
- c - 绘制非客户区的问题 - Win32
- javascript - javascript中-x和x之间的随机元素
- sql - 如何在sql中查找只有年份的数据