首页 > 解决方案 > RXJS 在嵌套数组中调用 api 并将结果合并到数组中

问题描述

我有一个包含一系列家庭的对象。这些家族中的每一个都拥有一系列家族成员对象。每个家庭成员都有一份合同,目前不存在。我的任务是从 rest api 中获取合同并将其合并到成员对象中。

Object {
 content: [{
  familiId: '1',
  familyMemmbers: [
   { id: '1'
     name: 'Tom'
     ...
    },
    { id: '2'
     name: 'Peter'
     ...
    }
   ]
 },
{
  familiId: '2',
  familyMemmbers: [
   { id: '1'
     name: 'Paul'
     ...
    },
    { id: '2'
     name: 'Joe'
     ...
    }
   ]
 }]
}
this.service.getFamilies().switchMap(familiyPage => from(familiyPage.content))
          .switchMap(family => from(family.familyMembers)).mergeMap(member => this.service.getContract(member.id).map(contract => {
          return {...member, contract}

我的方法{ id: 1, name: 'Tom', contract: ....}在第一次发射和{ id: 2, name: 'Peter', contract: ....}第二次发射、{ id: 1, name: 'Paul', contract: ....}第三次发射和{ id: 2, name: 'Joe', contract: ....}第四次发射时返回对象。

我想要的是只有一个包含整个数据结构的发射。IE

Object {
 content: [{
  familiId: '1',
  familyMemmbers: [
   { id: '1',
     name: 'Tom',
     contract: {...},
     ...
    },
    { id: '2',
     name: 'Peter',
     contract: {...},
     ...
    }
   ]
 }, ...]
}

标签: javascriptangularrestrxjs

解决方案


用于forkJoin将可观察成员数组分组为可观察成员数组。然后使用toArray将可观察的族分组为可观察的族数组。如果mergeMap您不关心家庭的顺序,或者concatMap如果您想保持家庭的原始顺序,请使用。

this.service.getFamilies().pipe(
  // use concatMap instead of mergeMap if you want to keep the families in their original order
  mergeMap(family => {
    // array of observables
    const members$ = family.familyMembers.map(member => {
      return getContract(member.id).pipe(map(contract => {...member, contract});
    });

    // use forkJoin to return single observable that returns array of results
    return forkJoin(members$).pipe(map(familyMembers => {...family, familyMembers}));
  }),
  // combine all the families back into an array of families
  toArray());

推荐阅读