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

如何用await替代then?Promise.all后异步请求返回空数组排查

问题:Promise.all后异步请求结果无法正确返回接口响应

问题描述

在Node.js项目中使用Supabase-Pg SQL执行数据库查询时,希望在Promise.all解析完一组异步请求后,遍历结果发起新请求并将结果存入数组。但该数组在控制台能正常打印,接口返回却为空。推测响应在Promise完成前已发送,但不清楚问题根源,也不知道如何用await替代then实现需求。相关代码如下:

export const getReportMonthly = async(req: Request & any, res: Response, next: NextFunction) => {
    try {

      let usersxData: UsersxModalidadxRolxJob[] = [];
      let data_monthly: HoursActivityWeeklySummary[] = [];
      let attendance_schedule: AttendanceSchedule[] = [];
      let time_off_request: TimeOffRequestRpc[] = [];
      let configs: IndicatorConfigs[] = [];

      const supabaseService = new SupabaseService();

      const promises = [
        supabaseService.getSummaryWeekRpcWihoutFreelancers(req.query.fecha_inicio, req.query.fecha_final).then(dataFromDB => {
          data_monthly = dataFromDB as any;
        }),
        supabaseService.getUsersEntity(res).then(dataFromDB => {
          usersxData = dataFromDB as any;
        }),
        supabaseService.getAttendaceScheduleRpc(req.query.fecha_inicio, req.query.fecha_final).then(dataFromDB => {
          attendance_schedule = dataFromDB as any;
        }),
        supabaseService.getTimeOffRequestRpc(req.query.fecha_inicio, req.query.fecha_final).then(dataFromDB => {
          time_off_request = dataFromDB as any;
        }),
        supabaseService.getConfigs(res).then(dataFromDB => {
          configs = dataFromDB;
        }),

      ];

      let attendanceInMonthly = new Array();
      await Promise.all(promises).then(() => {
        attendance_schedule.forEach(element => {
          let start_date = element.date_start.toString();
          let end_date = element.date_end.toString();

          supabaseService.getTrackedByDateAndIDArray(start_date, end_date).then(item => {
            console.log(item);
            attendanceInMonthly.push(item);
          });
        });
      })

      res.json(attendanceInMonthly)

    } catch (error) {
      console.log(error);
      res.status(500).json({
        title: 'API-CIT Error',
        message: 'Internal server error'
      });
    }
}

问题根源

  1. 未等待后续异步请求完成:await Promise.all(promises)只等待了初始的5个请求完成,但在then回调里的forEach中发起的getTrackedByDateAndIDArray请求都是异步的,代码没有等待这些请求完成就直接执行了res.json(attendanceInMonthly),此时数组还没被填充,所以返回空。
  2. 混用await和then导致逻辑混乱:已经使用了async/await语法,却仍用then处理Promise,不仅增加代码复杂度,还容易忽略异步流程的等待逻辑。

解决方法

步骤1:用await替代初始then,简化代码

把初始promises数组里的then替换为直接返回Promise,然后用解构赋值接收结果,避免额外的变量赋值操作。

步骤2:等待forEach中的所有异步请求

将forEach改为map,把每个异步请求转为Promise并收集到新数组中,再用await Promise.all等待所有请求完成,结果会直接填充到attendanceInMonthly数组。

修改后的完整代码

export const getReportMonthly = async(req: Request & any, res: Response, next: NextFunction) => {
    try {
      const supabaseService = new SupabaseService();

      // 用await直接接收所有初始请求的结果,替代then赋值
      const [
        data_monthly,
        usersxData,
        attendance_schedule,
        time_off_request,
        configs
      ] = await Promise.all([
        supabaseService.getSummaryWeekRpcWihoutFreelancers(req.query.fecha_inicio, req.query.fecha_final),
        supabaseService.getUsersEntity(res),
        supabaseService.getAttendaceScheduleRpc(req.query.fecha_inicio, req.query.fecha_final),
        supabaseService.getTimeOffRequestRpc(req.query.fecha_inicio, req.query.fecha_final),
        supabaseService.getConfigs(res)
      ]);

      // 用map生成Promise数组,再await Promise.all等待所有请求完成
      const attendanceInMonthly = await Promise.all(
        attendance_schedule.map(element => {
          const start_date = element.date_start.toString();
          const end_date = element.date_end.toString();
          // 直接返回每个异步请求的Promise
          return supabaseService.getTrackedByDateAndIDArray(start_date, end_date);
        })
      );

      // 所有请求完成后再返回响应
      res.json(attendanceInMonthly)

    } catch (error) {
      console.log(error);
      res.status(500).json({
        title: 'API-CIT Error',
        message: 'Internal server error'
      });
    }
}

关键说明

  • 避免混用await和then:async/await是更直观的异步处理方式,能让代码逻辑更线性,减少嵌套和异步流程遗漏。
  • forEach不适合处理异步操作:forEach不会等待内部的异步任务完成,改用map生成Promise数组后用Promise.all等待,是处理批量异步请求的标准方式。
  • 确保所有异步操作完成后再发送响应:只有当所有数据库请求都完成并拿到结果后,再调用res.json,才能保证返回的数据是完整的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 16:40:37