Reputation: 2006
I'm kind off new to rxjs, and I've a fairly simple case that I can't work out in angular.
I've a http call to retrieve a group, this group contains a list of "buddy ids", a list of "genre ids" and a "region id".
To get the buddy objects trough the "buddy ids", I have to make a call to an API trough my service ( which return 1 buddy with given id ).
To get my genre objects, I can retrieve them form my store, same for region.
The problem is I can't have a solution worked out with pipes.
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]) => {
});
So the first mergeMap will be to get all the results togehter in 1 subscribe, then I've 3 sub calls to get the buddies, genres and the region.
I'd like to have my initial response ( the group ) and the results of the 3 subcalls in 1 subscribe, obviously this solution doesn't work, and I can't seem to get something else to work.
Any help would be appreciated, thanks !
Upvotes: 7
Views: 9311
Reputation: 2910
This version is a little more verbose, but might be easier to reason about as it is divided into several chunks. Haven't tested it though.
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]) => {});
Upvotes: 2
Reputation: 5364
Seems you have too many inner mergeMap
s. Try this
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]) => {});
The main issue was that you've combined "constructing" methods that create Observables (like forkJoin
) with operators that operate on existing Observables (like switchMap
or mergeMap
).
Test the difference yourself: switchMap
vs forkJoin
I've written this w/o deep testing, so it might not work immediately :)
Upvotes: 5