blazkovicz
blazkovicz

Reputation: 792

RxJS example of loading and enriching a list of items

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

Answers (2)

frido
frido

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

Neji Sghair
Neji Sghair

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

Related Questions