首页 > 解决方案 > 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');
});

标签: node.jsexpress

解决方案


我认为这可以解决问题

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 函数的原因


推荐阅读