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

如何从Array.reduce返回Promise?异步处理遇数据缺失问题

问题描述

我正在使用Array.reduce遍历对象数组,并尝试从中返回Promise。在reduce方法内完成修改后,Promise解析出的对象中reviewCards['departments']有正常数据,但reviewCards['genders']为空,我认为并非所有Promise都已正确解析。

请问如何将最终对象以Promise形式返回?

public getCompanyReviewCards(
   reviewGroups: ICompanyReviewGroups,
   reviews: CompanyReview[],
): Promise<{[key: string]: ICompanyReviewCard}> {
  
   return new Promise((resolve, reject) => { 
      const reviewCards = Object.keys(reviewGroups).reduce(
         async (reviewCards: ICompanyReviewCards, groupKey: string) => {

            const group = reviewGroups[groupKey];
            reviewCards['genders'] = reviewCards['genders'] || [];
            reviewCards['departments'] = reviewCards['departments'] || [];

            //Department wise cards
            //This block is executing properly
            if (groupKey === '_departmentGroup') {
                 const departmentsCards = await this.getCardsByDepartments(group);
                 reviewCards['departments'] = departmentsCards;
            }

            //Gender wise cards
            //This block is not executing properly
            if (groupKey === '_genderGroup') {
                 const gendersCards = await this.getCardsByGender(group);
                 reviewCards['genders'] = gendersCards;
            }

            return reviewCards;

         },Object.create(null),
      );

   resolve(reviewCards);

   })
}

问题原因

核心问题是你把async函数作为reduce的回调,导致累加器每次都是Promise,而非直接的对象。第一次迭代时,回调返回的是Promise,但第二次迭代时,reviewCards参数是上一次的Promise,你直接对它操作(比如reviewCards['genders'] = ...)其实是在Promise对象上添加属性,而不是等待Promise解析后的实际对象。这就导致后续的异步操作没有正确作用到目标对象上,最终genders数据丢失。


修正方案

需要在reduce的回调里先等待上一次的Promise解析,拿到实际的reviewCards对象后再进行操作。同时,不需要额外包裹一层new Promise,因为reduce最终会返回一个Promise,直接返回它即可:

public getCompanyReviewCards(
  reviewGroups: ICompanyReviewGroups,
  reviews: CompanyReview[],
): Promise<{[key: string]: ICompanyReviewCard}> {
  // 直接返回reduce生成的Promise
  return Object.keys(reviewGroups).reduce(
    async (accPromise, groupKey: string) => {
      // 先等待上一次的Promise完成,拿到实际的reviewCards对象
      const reviewCards = await accPromise;
      const group = reviewGroups[groupKey];

      // 初始化默认值
      if (!reviewCards.genders) reviewCards.genders = [];
      if (!reviewCards.departments) reviewCards.departments = [];

      if (groupKey === '_departmentGroup') {
        const departmentsCards = await this.getCardsByDepartments(group);
        reviewCards.departments = departmentsCards;
      }

      if (groupKey === '_genderGroup') {
        const gendersCards = await this.getCardsByGender(group);
        reviewCards.genders = gendersCards;
      }

      return reviewCards;
    },
    // 初始值是一个resolved的Promise,包含空对象
    Promise.resolve(Object.create(null) as ICompanyReviewCards)
  );
}

关键修改点

  • 初始值改为Promise.resolve的空对象:确保第一次迭代时accPromise是一个已解析的Promise,能拿到实际对象。
  • 每次迭代先等待accPromise解析:const reviewCards = await accPromise,确保操作的是实际的对象而非Promise。
  • 去掉外层多余的new Promise:reduce最终返回的就是Promise,直接return即可,避免嵌套Promise。

这样修改后,所有异步操作都会按顺序执行,genders和departments的数据都会正确填充到最终对象中。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 19:10:50