Reputation: 1647
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
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