简体   繁体   English

使用服务文件时链 http 请求

[英]Chain http requests when using service file

I wish to combine 2 http requests together to make this a little more elegant however most examples I see online use mergemap however they are not making the http requests via a service file.我希望将 2 个 http 请求组合在一起,以使其更加优雅,但是我在网上看到的大多数示例都使用mergemap但是它们没有通过服务文件发出 http 请求。 Any ideas on how I can approach this?关于如何解决这个问题的任何想法? I have the following code:我有以下代码:

ngOnInit() {
this.getMatrixData();
}

getMatrixData() {

      this.httpService.getPackageAvailabilityListForPricingMatrix()
          .subscribe((res) => {

              this.packageListItems = res.body;
              this.getGradeItems();

          });

  }

getGradeItems() {
      this.httpService.getHospitalityGradesList()
          .subscribe((res) => {

              this.allGrades = res.body;
              this.makeMatrix();
          });
  }

makeMatrix()
{
console.log("Now combine data");
}

My service file just returns the following:我的服务文件只返回以下内容:

getPackageAvailabilityListForPricingMatrix(): Observable<any> {
        return this.http.get("apiPath", { responseType: 'json', observe: 'response', headers: new HttpHeaders().set("Authorization", "bearer " + this.getUserToken() + " ") });
    }

getHospitalityGradesList(): Observable<any> {
        return this.http.get("apiPath", { responseType: 'json', observe: 'response', headers: new HttpHeaders().set("Authorization", "bearer " + this.getUserToken() + " ") });
    }

I think you can make use of forkJoin that will execute both requests together我认为您可以使用forkJoin将两个请求一起执行

makeMatrix() {
forkJoin(this.httpService.getPackageAvailabilityListForPricingMatrix(), 
this.httpService.getHospitalityGradesList())
 .subscribe(
  ([r1, r2]) => {

  }
 );
}

You can use combineLatest from rxjs .您可以使用来自combineLatestrxjs

import { combineLatest } from 'rxjs';
ngOnInit() {
    combineLatest([
        this.httpService.getPackageAvailabilityListForPricingMatrix(),
        this.httpService.getHospitalityGradesList()
    ]).subscribe(
       ([res1, res2]) => {
          // res1 contains response of getPackageAvailabilityListForPricingMatrix()
          // res2 contains response of getHospitalityGradesList()
          this.makeMatrix();
       }
    );
}

PS : This is only possible when your service function returns observable and you dont have dependent API calls. PS:只有当您的服务 function 返回observable并且您没有依赖 API 调用时,这才有可能。

This is easily done with a mergeMap , or the more semantically correct one concatMap :这可以通过mergeMap或语义更正确的concatMap轻松完成:

ngOnInit(): void {
  this.this.httpService.getPackageAvailabilityListForPricingMatrix().pipe(
    concatMap((res) => {
      this.packageListItems = res.body;

      return this.httpService.getHospitalityGradesList()
    }),
    tap((res) => this.allGrades = res.body)
  ).subscribe(() => {
    this.makeMatrix()
  });
}

if the second request does not depend on the first request, you can also use forkJoin , which is again semantically more correct than combineLatest .如果第二个请求不依赖于第一个请求,您还可以使用forkJoin ,这在语义上再次比combineLatest更正确。 You have to pass in an array of observables, of an object map.你必须传入一个可观察的数组,一个 object map。 The observable paramater list is deprecated:不推荐使用可观察参数列表:

ngOnInit(): void {
  forkJoin([
    this.httpService.getPackageAvailabilityListForPricingMatrix(),
    this.httpService.getHospitalityGradesList()
  ]).subscribe(([ packageListItems, allGrades ]) => {
    this.pacakgeListItems = packageListItems.body;
    this.allGrades = allGrades.body;
  });
}

A third option would be to have the nice possibility of using the async pipe from angular, which will make your code even cleaner:第三种选择是很有可能使用来自 angular 的async pipe,这将使您的代码更加简洁:

readonly packageListItems$ = this.httpService.getPackageAvailabilityListForPricingMatrix().pipe(
  map(({ body }) => body), 
  shareReplay(1)
);

readonly allGrades$ = this.httpService.getHospitalityGradesList().pipe(
  map(({ body }) => body), 
  shareReplay(1)
);

All you need to do when you use this in your template is:在模板中使用它时,您需要做的就是:

<div *ngFor="let package of packageListItems$ | async"></div>

This way you don't have to subscribe in your component, which is sort of frowned upon, and also when you navigate away from the component and the request is not finished yet, it is already automatically unsubscribed and won't trigger any unwanted effeccts.这样您就不必订阅您的组件,这有点令人不悦,而且当您离开组件并且请求尚未完成时,它已经自动取消订阅并且不会触发任何不需要的效果.

I've added the shareReplay for convenience.为方便起见,我添加了shareReplay This will replay the last value on subscription.这将重播订阅的最后一个值。 This way if you subscribe to it in your code to get the last value, it does not fire the http request again but just returns the last value这样,如果您在代码中订阅它以获取最后一个值,它不会再次触发 http 请求,而只会返回最后一个值

side-note 2: If you do use forkJoin , make sure your httpService catches any network error it might receive.旁注 2:如果您确实使用forkJoin ,请确保您的httpService捕获它可能收到的任何网络错误。 If one of the observables fail, the entire forkJoin will fail and any request that did succeed will not reach the subscriber.如果其中一个 observables 失败,整个forkJoin将失败,并且任何成功的请求都不会到达订阅者。 So do use catchError inside your httpService and perhaps return an empty array when the response is supposed to be an array.所以在你的httpService中使用catchError并且当响应应该是一个数组时可能返回一个空数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM