Reputation: 161
I have an Angular-resolver that fetch data from the backend. I have the following calls to perform:
GetProject(projectId): Observable<IProject>
GetSites(projectId): Observable<ISites[]>
GetPersons(siteId): Observable<IPerson[]>
I'm trying to use combineLatest but not sure how to use RxJs in my scenario. I want all request to complete before resolving, but GetPersons() should have the id of the first item in GetSites() result as input. How is this done?
Upvotes: 3
Views: 1651
Reputation: 9124
this.project$ = this.myService.getProject(projectId);
this.sites$ = this.myService.getSites(projectId);
this.persons$ = this.sites$.pipe(
switchMap(
(sites: ISites[]) => merge(...sites.map((site: ISites) => this.myService.getPersons(site.id))),
),
); // that should result in Observable<IPerson[][]>, you likely need to flatten it
Upvotes: 0
Reputation:
Create a replay subject :
const sub = new ReplaySubject(3);
Then make your calls
this.getProject(1).pipe(
tap(project => sub.next(project)),
switchMap(project => this.getSites(1)),
tap(sites => sub.next(sites)),
switchMap(sites => this.getPersons(sites[0].id)),
tap(person => sub.next(person))
);
Your replay subject will contain the project as first value, the sites as second value, the person as thrid value.
You can do it with the combineLatest
format with a BehaviorSubject
.
const obs = new BehaviorSubject([]);
const add = val => obs.pipe(
take(1),
map(v => ([...v, val]))
).subscribe(v => obs.next(v));
this.getProject(1).pipe(
tap(project => add(project)),
switchMap(project => this.getSites(1)),
tap(sites => add(sites)),
switchMap(sites => this.getPersons(sites[0].id)),
tap(person => add(person))
);
This time, the value returned will be an array of all of your values.
Finally, you have the complicated syntax to concatenate them, without a subject.
this.getProject(1).pipe(
switchMap(project => this.getSites(1).pipe(map(sites => ([project, sites])))),
switchMap(([project, sites]) => this.getPersons(sites[0].id).pipe(map(person => ([project, sites, map])))),
);
Upvotes: 2
Reputation: 96889
It looks more like you want to just concat several calls:
forkJoin([GetProject(projectId), GetSites(projectId)]).pipe(
concatMap(([project, sites]) => {
const siteId = /* whatever here */;
return GetPersons(siteId);
}),
).subscribe(...);
It also depends on whether you want to receive in the observer all responses or just the last one. If you want all responses then you'll need to chain GetPersons
with map
and append the first two responses:
GetPersons(siteId).pipe(
map(persons => [project, sites, persons]),
)
Upvotes: 3