Multiple HTTP Requests with RxJS, with parameters

倖福魔咒の 提交于 2019-12-08 05:25:02

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!