Reputation: 792
I want to fetch an array containing multiple items and then fetch and add additional data to every item in that array.
How can I implement the method getEnrichedItemsList
given the implementations for getItemsList
and getRelatedObject
?
interface RelatedObject = {}
interface Item = {
id: string;
relatedObjectId: string;
}
interface EnrichedItem = Item & {
relatedObject: RelatedObject ;
}
interface apiService = {
getItemsList: (query: string) => Observable<Item[]>; // implemented
getRelatedObject: (relatedObjectId: string) => Observable<RelatedObject>; // implemented
getEnrichedItemsList: (query: string) => Observable<EnrichedItem[]>; // HOW TO IMPLEMENT?
}
Upvotes: 2
Views: 1132
Reputation: 14109
Use forkJoin
to execute multiple requests simultaneously and emit an array of items with the same order as the input array.
getEnrichedItemsList(query: string): Observable<EnrichedItem[]> {
return this.getItemsList(query).pipe(
switchMap(items => forkJoin(items.map(item => this.enrichItem(item))))
)
}
enrichItem(item: Item): Observable<EnrichedItem> {
return this.getRelatedObject(item.relatedObjectId).pipe(
map(relatedObject => ({ ...item, relatedObject } as EnrichedItem))
)
}
This guarantees that the final order of enriched items is the same as received by this.getItemsList(query)
which may not be the case when using from
and mergeMap
.
Upvotes: 3
Reputation: 174
Something like this ?
getEnrichedItemsList(query: string): Observable<EnrichedItem []>{
return this.getItemsList(query).pipe(
mergeMap(items => from(items)),
mergeMap(item => this.getRelatedObject(item.relatedObjectId).pipe(
map(relatedObject => Object.assign(item,{relatedObject}))
))
);
}
Full example : https://stackblitz.com/edit/rxjs-ahllnu
Upvotes: 4