Reputation: 149
I am using Observables, I have a use case where:
Page[]
The concern is once all of those requests are completed then have to do some action.
Upvotes: 7
Views: 15875
Reputation: 6325
you need use mergeMap and forkJoin
When using forkJoin
you can fire parallel request at the same time and it will wait till all requests are completed.
this.http.get('/api/pages/')
.map((res: any) => res.json())
.mergeMap((pages: any[]) => {
if (pages.length > 0) {
return Observable.forkJoin(
pages.map((page: any) => {
return this.http.get('/api/sections/' + page_id)
.map((res: any) => {
let section: any = res.json();
// do your operation and return
return section;
});
});
);
}
return Observable.of([]);
});
}
Upvotes: 11
Reputation: 96891
In general when nesting async calls try to stay as flat as possible. Otherwise, you're creating callback hell which make things even more complicated than just with regular iterative code:
this.http.get('/api/pages/')
.map((res: Response) => res.json())
.concatMap((pages: Page[]) => {
const observables = pages.map(p => this.http.get('whatever' + p.id));
return Observable.forkJoin(observables, (...results) =>
results.map((result, i) => {
pages[i].sections = result;
return pages[i];
})
)
})
.subscribe(pagesWithSections => ...);
The forkJoin()
operator takes as argument a selector function that lets you work with the results of all the source Observables. I'm using it to update the original pages
array and return it.
Upvotes: 8