RXJS - 对属性数组的多个可观察调用

Tan*_*uyB 5 observable rxjs typescript angular

我对 rxjs 不太熟悉,而且我有一个相当简单的案例,我无法在 angular 中解决。

我有一个 http 调用来检索一个组,该组包含一个“好友 ID”列表、一个“流派 ID”列表和一个“区域 ID”。

要通过“好友 id”获取好友对象,我必须通过我的服务调用 API(返回 1 个给定 id 的好友)。

为了获取我的流派对象,我可以从我的商店中检索它们,对于地区也是如此。

问题是我无法用管道找到解决方案。

this.buddyService.getGroup(groupId).pipe(
    mergeMap((group) => forkJoin(
          mergeMap(() => forkJoin(group.buddyIds.map((id) => this.buddyService.getBuddy(id)))), 
          mergeMap(() => forkJoin(group.genreIds.map((id) => this.store.select(GenreState.genre(id))))),
          switchMap(() => this.store.select(RegionState.region(group.regionId))))
    ), takeUntil(this.destroyed$)
).subscribe(([group, buddies, genres, region]) => {

});
Run Code Online (Sandbox Code Playgroud)

所以第一个 mergeMap 将在 1 次订阅中获得所有结果,然后我有 3 个子调用来获取好友、流派和地区。

我想要我的初始响应(组)和 1 个订阅中的 3 个子调用的结果,显然这个解决方案不起作用,我似乎无法得到其他东西。

任何帮助将不胜感激,谢谢!

kos*_*kos 5

看来你的内心太多了mergeMap。尝试这个

this.buddyService.getGroup(groupId).pipe(
  mergeMap((group) => forkJoin(
    of(group),
    forkJoin(...group.buddyIds.map((id) => this.buddyService.getBuddy(id))), 
    forkJoin(...group.genreIds.map((id) => this.store.select(GenreState.genre(id)))),
    this.store.select(RegionState.region(group.regionId)))
  ),
  takeUntil(this.destroyed$)
)
.subscribe(([group, buddies, genres, region]) => {});
Run Code Online (Sandbox Code Playgroud)

主要问题是您将创建Observables(如forkJoin)的“构造”方法与对现有Observables 进行操作的运算符(如switchMapmergeMap)结合起来。

自己测试一下差异:switchMapvsforkJoin

我写的这个没有进行深入测试,所以它可能不会立即起作用:)


Sno*_*Dan 2

这个版本有点冗长,但可能更容易推理,因为它分为几个块。不过还没有测试过。

import {combineLatest} from 'rxjs';

...

  const group$ = this.buddyService.getGroup(groupId);
  const buddies$ = group$.pipe(mergeMap(group => combineLatest(group.buddyIds.map((id) => this.buddyService.getBuddy(id))));
  const genres$ = group$.pipe(mergeMap(group => combineLatest(group.genreIds.map((id) => this.store.select(GenreState.genre(id))));
  const region$ = group$.pipe(switchMap(group => this.store.select(RegionState.region(group.regionId)))));

  combineLatest([group$, buddies$, genres$, region$])
    .pipe(takeUntil(this.destroyed$))
    .subscribe(([group, buddies, genres, region]) => {});
Run Code Online (Sandbox Code Playgroud)