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

异步查询完成后返回每小时生产计数结果的问题求助

问题分析与解决方案

你的问题核心是异步操作的执行时机没把握好——你在所有数据库查询还没完成的时候就返回了响应,这时候productionCount自然是空的。另外代码里还有几个小错误,我帮你一步步修正:

关键问题点

  • 你在async.each的异步任务还全部完成前,就调用了res.json,这是典型的异步顺序错误
  • 迭代data数组时,错误地使用了data.from(整个数组的属性),而不是当前迭代的单个时间区间对象的from和to
  • 多余使用了async.waterfall,这里只需要单次异步查询,没必要用瀑布流
  • 时间区间的循环计算有问题,会导致所有时间戳指向同一个对象(因为Date是引用类型)

修正后的完整代码

exports.production_report = function(req, res) {
  ShiftTiming.findOne({"clientId": req.body.clientId}, function (err, shiftTiming) {
    if (err) {
      return res.send(err);
    }

    const data = [];
    const productionCount = [];
    const baseDate = new Date(req.body.eDate);

    // 正确生成24个小时的时间区间
    for (let i = 0; i <= 23; i++) {
      // 每次循环都创建新的Date对象,避免引用覆盖
      const from = new Date(baseDate);
      // 按你的逻辑计算基础小时和分钟(适配shiftA的结构)
      const baseHour = shiftTiming.shiftA[0] + shiftTiming.shiftA[1];
      const baseMinute = shiftTiming.shiftA[3] + shiftTiming.shiftA[4];
      from.setHours(baseHour + i);
      from.setMinutes(baseMinute);

      const to = new Date(from);
      to.setHours(to.getHours() + 1);

      data.push({"from": from, "to": to});
    }

    // 使用async.each处理所有异步查询
    async.each(data, function(timeRange, callback) {
      // 查询当前时间区间的计数,使用当前迭代的timeRange的from和to
      CycleTime.count({
        "machineId": req.body.machineId,
        "startDateTime": {
          $gte: timeRange.from,
          $lt: timeRange.to
        }
      }).exec(function(err, count) {
        if (err) {
          return callback(err); // 传递错误给async.each的回调
        }
        productionCount.push({count});
        callback(); // 标记当前迭代任务完成
      });
    }, function(err) {
      // 所有异步任务完成后的回调
      if (err) {
        return res.send(err);
      }
      // 现在productionCount已经填充完成,返回响应
      res.json({ data: data, productionCount: productionCount });
    });
  });
};

核心修改说明

  1. 异步流程控制:把res.json移到async.each的最终回调里,确保所有数据库查询完成后再返回数据
  2. 迭代参数修正:在async.each的迭代函数里,使用当前的timeRange(代替你原来的user)来获取单个时间区间的from和to,而不是错误地引用整个data数组
  3. 时间对象创建:每次循环都创建新的Date对象,避免因为Date是引用类型导致所有时间区间被覆盖的问题
  4. 简化异步逻辑:移除了多余的async.waterfall,因为这里只需要执行一次异步查询,不需要多步骤的瀑布流操作
  5. 错误处理优化:在每个异步步骤都正确传递错误,确保错误能被捕获并返回给客户端

测试验证

当你用示例请求调用这个接口时,productionCount会被填充为对应每个时间区间的计数,和data数组的元素一一对应。

内容的提问来源于stack exchange,提问作者Jayesh Rohira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:43:55