问题
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
回答1:
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.
回答2:
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 =>{
})
回答3:
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