I call this api
https://jokerleb.com/wp-json/wp/v2/ads/
I grab the id of each ad and then I append it to this url
https://jokerleb.com/wp-json/wp/v2/media?parent=24385
My code is
loadAds() {
let i = 0;
this.HttpClient.get(ENV.site_url + ENV.ads_url)
.subscribe(res => {
this.ads = this.ads.concat(res);
this.HttpClient.get(ENV.site_url + ENV.ads_thumb_url + this.ads[i].id + "&&ads/" + this.ads[i].id)
.subscribe(res => {
this.items = this.items.concat(res);
console.log(ENV.site_url + ENV.ads_thumb_url + this.ads[i].id + "&&ads/" + this.ads[i].id);
i++;
})
}
)
}
The code works but:
- I end up with two different arrays, I'm not able to merge them correctly into an array
items - I hate the fact that I have to do two separate subscriptions, it works but it feels wrong
Basically I want to end up with an array containing all the items from both endpoints.
So object id=24385 should return an array of
https://jokerleb.com/wp-json/wp/v2/ads/24385
And
https://jokerleb.com/wp-json/wp/v2/media?parent=24385
What you need to do is merge the two lists using concatMap.
For example:
getService1(id1).pipe(
// take array1 and return [array1, array2]
concatMap( array1=> return zip(of(array1), getService2(array1[information])))
// concat Array1 and array2
map( [array1, array2] => array1.concat(array2))
)
.subscribe( combinedArray => ...)
If your services emit 1 item each, you can replace concatMap with switchMap, mergeMap, or exhaustMap; they all behave same in this context. Additionally, you can also substitute zip with forkJoin. On the contrary, if your services emit more than 1 value, you will have to choose the one that behaves according to your needs.
You can switchMap to second call where you do forkJoin (send all calls and wait for the final array of response)
this.HttpClient.get(ENV.site_url + ENV.ads_url).pipe(
switchMap(res => {
this.ads = this.ads.concat(res);
let obs = this.ads.map(ad => this.HttpClient.get(ENV.site_url + ENV.ads_thumb_url + ad.id + "&&ads/" + ad.id);//create an observable array
return forkJoin(...obs).pipe(map(res=>res.concat(this.ads)));//map the response with initial array and return concatenated array.
})
).subscribe(finalArray =>{
})
Thanks for everyone who answered, I'm gonna pick a randomly accepted answer because they're excellent, I solved it like this though.
Provider:
getAds(): Observable<any[]> {
return this.http.get(ENV.site_url + ENV.ads_url)
.flatMap((ads: any[]) => {
if (ads.length > 0) {
return Observable.forkJoin(
ads.map((ad: any) => {
return this.http.get(ENV.site_url + ENV.ads_thumb_url + ad.id)
.map((res: any) => {
let media: any = res;
ad.media = media;
return ad;
});
})
);
}
return Observable.of([]);
});
}
and the provider is
Home.ts
ngOnInit() {
this.adsProvider.getAds().subscribe((data: any) => {
this.items = data;
});
}
Credit to this article: Combining Observables in series and in parallel
来源:https://stackoverflow.com/questions/51379624/multiple-http-requests-with-rxjs-with-parameters