You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让回调函数等待数据库调用完成?Node.js后端求助

问题分析

你遇到的核心问题是:forEach 不支持异步等待——哪怕给它传了async回调函数,forEach也会直接遍历完所有元素,不会等待每个回调里的await操作完成。这就导致后续处理rows的代码(以及最终的res.send)在异步DB调用getIdDetails结束前就执行了,自然拿不到datas的值。

另外你的代码还有几个额外问题:

  • 第二个forEach里引用了未定义的row变量,应该是dets.dept_name
  • finally里调用res.send会导致重复发送响应(then或catch里已经可能发送了)
  • await和.then()混用,代码逻辑混乱
  • CommonUtil.formatDetails传入的是整个rows数组,看起来应该是处理单个row
解决方案:用Promise.all + map替代forEach

map可以把每个row处理成一个Promise,再用Promise.all等待所有Promise完成,确保所有异步DB调用都结束后再处理结果和发送响应。

修正后的代码如下:

this.router.get("/:version/:dept/:id", async (req: any, res: any) => {
  try {
    logger.trace("getDetails call initialized");
    const dept = req.params.dept;
    const id = req.params.id;
    const deptDao = new deptDAO();
    let finalDetails = [];
    let simpleDetail = {};

    // 首次DB调用
    const rows = await deptDao.getdetails(dept, id);

    // 用map生成所有异步操作的Promise数组,再用Promise.all等待全部完成
    await Promise.all(rows.map(async (row: any) => {
      if (row.dept_name === "Science") {
        try {
          const idDao = new IDDao();
          // 统一用await替代then,逻辑更清晰
          const result = await idDao.getIdDetails(dept, row.valueId);
          if (result[0]?.std_details?.datas) {
            row.datas = result[0].std_details.datas;
          }
        } catch (error) {
          logger.error('failed', error);
        }
      } else {
        // 修正为处理单个row而非整个rows数组
        CommonUtil.formatDetails(dept, row);
      }
    }));

    // 现在所有异步操作都完成了,可以安全处理rows
    rows.forEach((dets) => {
      if (dets.dept_name === "Science") {
        simpleDetail = dets;
      } else {
        finalDetails.push(dets);
      }
    });

    // 发送响应
    res.status(200).send({ status: "success", depts: finalDetails, dept: simpleDetail });
  } catch (ex) {
    logger.error('整体请求失败', ex);
    res.status(500).send({ status: "failed", message: ex.message });
  }
});
关键改动说明
  • 把路由回调改成async函数,内部用await替代.then()链式调用,代码更简洁易读
  • 用rows.map(async row => {...})生成每个row对应的异步处理Promise,再用await Promise.all(...)等待所有异步DB调用完成
  • 移除原代码中的.then()、.catch()、.finally()链式结构,改用try/catch处理全局错误
  • 修正CommonUtil.formatDetails的参数,改为处理单个row
  • 移除finally里的res.send,避免重复发送响应,确保只有在所有操作完成后才发送成功响应

内容的提问来源于stack exchange,提问作者Ajay Antonyraj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 03:16:04