Aico Klein Ovink
Aico Klein Ovink

Reputation: 1647

Iterating over Observable values and subscribe to new Observable

Let's say if have an Array inside an Observable, for each value of that array, it want to make an API call (which returns an Observable again). I'll break it down to a simple example. Because I need to iterate over the first observables values, how do I make sure that data contains the actual data, and not another observable?

I tried switchMap, mergeMap, etc..

const observables = Observable.of([{ id: 1 }, { id: 2 }]);
const data = Observable.of('data');

observables.pipe(

  // I tried a lot, something like this
  map(values => {
    if(Array.isArray(values)) {
      values.map(value => value.data = data); // data will be an Observable
    }
    return values;
  })

).subscribe(result => {
  console.log(result) // I want: [{ id: 1, data: 'data' }, { ... }]
});

Upvotes: 1

Views: 4837

Answers (1)

Ashish Ranjan
Ashish Ranjan

Reputation: 12970

Depending upon your requirement of sending API requests you could use any of mergeMap, concatMap, forkJoin, etc.

I will be giving an example using forkJoin and mergeMap

const observableData: Observable<{ id: number; data?: any }[]> = of([
  { id: 11 },
  { id: 12 }
]);

return observableData.pipe(
  mergeMap(values => {
    // first map all the observales to make an array for API calls
    let apiArray = values.map(eachValue => {
      return this.yourApiService.getData(eachValue.id);
    });
    // now you have to make API calls
    return forkJoin(...apiArray).pipe(
      map(apiData => {
        // now modify your result to contain the data from API
        // apiData will be an array conating results from API calls
        // **note:** forkJoin will return the data in the same sequence teh requests were sent so doing a `forEach` works here
        values.forEach((eachOriginalValue, index) => {
          eachOriginalValue.data = apiData[index].name; // use the key in which you get data from API
        });
        return values;
      }),
      catchError(e => {
        console.log("error", e);
        return of(e);
      })
    );
  })
);

See a working example here: https://stackblitz.com/edit/forkjoinwithmergemap?file=src%2Fapp%2Fapp.component.ts

Upvotes: 4

Related Questions