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

如何用async/await等待SQL响应,完成聚合后返回HTTP POST响应?

解决HTTP POST接口/getDataByWeek数据为空问题

开发/getDataByWeek接口时,需要按周查询SQL数据并聚合到数组后返回客户端,但当前代码执行后prod、scarti等数组始终为空,无法获取正确结果。

错误代码示例

app.post("/getDataByWeek", (req, res) => {
  async function queryDB(){
    let dataArray = [];
    var today = new Date();
    for(let i=0;i<=req.body.prev_week;i++){
        let currWeek = today;
        currWeek.setDate(currWeek.getDate() - i*7);
        dataArray.push(currWeek.toLocaleString().split(" ")[0].replace(",",""))
    }
    let scarti = [];
    let prod = [];
    let dateArray = [];
    let pool = await sql.connect(configSQL);
    let data =  pool.request()
    for(var i=dataArray.length - 1;i>0;i--){
      let startDate = normData(dataArray[i]);
      let endDate = normData(dataArray[i-1]);
      let query_string = "SELECT  SUM(qty_good) as PRODOTTE, SUM(qty_reject) as SCARTO FROM [MESDB].[dbo].[vw_oee_data] where ent_name = 'Scatolatrice' and cast(hour_end_local as time) BETWEEN '06:00:00.000' AND '21:00:00.000' and cast(hour_end_local as date) BETWEEN '" + startDate +"' AND '" + endDate + "'";
      
      await data.query(query_string,  function (err, recordset) { 
          prod.push(recordset.recordset[0].PRODOTTE)
          scarti.push(recordset.recordset[0].SCARTO)
          dateArray.push(endDate)             
      })
    }
    return prod,scarti,dateArray; 
  }
  queryDB().then((prod,scarti,dateArray)=>console.log(prod))
});

问题根源

  1. async/await与回调混用:await等待的是data.query的Promise,但同时传入的回调函数不会被await等待,导致循环结束时数组还未被赋值。
  2. 返回值错误:return prod,scarti,dateArray是逗号表达式,实际仅返回最后一个值dateArray,无法同时返回三个数组。
  3. 日期对象引用问题:let currWeek = today是引用赋值,循环中修改的是同一个Date实例,导致dataArray内的日期全部相同。
  4. SQL注入风险:直接拼接字符串生成SQL语句,存在严重的注入安全隐患。

修复后的代码

app.post("/getDataByWeek", async (req, res) => {
  try {
    async function queryDB() {
      let dataArray = [];
      const today = new Date();
      // 修复日期引用问题:每次循环创建新的Date实例
      for (let i = 0; i <= req.body.prev_week; i++) {
        const currWeek = new Date(today);
        currWeek.setDate(currWeek.getDate() - i * 7);
        dataArray.push(currWeek.toLocaleString().split(" ")[0].replace(",", ""));
      }

      const scarti = [];
      const prod = [];
      const dateArray = [];
      const pool = await sql.connect(configSQL);

      // 循环处理每周数据,确保等待每个查询完成
      for (let i = dataArray.length - 1; i > 0; i--) {
        const startDate = normData(dataArray[i]);
        const endDate = normData(dataArray[i - 1]);
        // 使用参数化查询避免SQL注入
        const queryString = `
          SELECT SUM(qty_good) as PRODOTTE, SUM(qty_reject) as SCARTO 
          FROM [MESDB].[dbo].[vw_oee_data] 
          WHERE ent_name = 'Scatolatrice' 
            AND CAST(hour_end_local AS time) BETWEEN '06:00:00.000' AND '21:00:00.000' 
            AND CAST(hour_end_local AS date) BETWEEN @startDate AND @endDate
        `;

        // 去掉回调,直接用await获取查询结果
        const result = await pool.request()
          .input('startDate', sql.Date, startDate)
          .input('endDate', sql.Date, endDate)
          .query(queryString);

        const record = result.recordset[0];
        prod.push(record.PRODOTTE ?? 0); // 处理NULL值,默认填充0
        scarti.push(record.SCARTO ?? 0);
        dateArray.push(endDate);
      }

      // 返回对象包含所有结果
      return { prod, scarti, dateArray };
    }

    const result = await queryDB();
    console.log(result.prod);
    // 给客户端返回JSON结果
    res.status(200).json(result);
  } catch (err) {
    // 错误处理,返回错误信息
    console.error(err);
    res.status(500).json({ error: '查询失败', details: err.message });
  }
});

关键改进说明

  • 日期处理修复:每次循环创建新的Date实例,避免修改同一个对象导致日期错误。
  • 正确使用async/await:移除data.query的回调函数,直接用await等待查询结果,确保数组在循环过程中被正确填充。
  • 返回值修正:用对象包装三个数组,保证所有结果能被正确返回。
  • SQL注入防护:改用参数化查询,将日期作为参数传入,避免直接拼接字符串。
  • 错误处理:添加try/catch捕获数据库连接和查询过程中的错误,给客户端返回明确的错误响应。

内容的提问来源于stack exchange,提问作者Mattia DELLI PRISCOLI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 00:33:16