Angular Http客户端发送到许多请求

时间:2019-01-22 21:26:23

标签: angular angular-http

大家好,我正在尝试通过HttpClient从'@ angular / common / http'发出一个简单的POST请求;

所以我有了一种看起来像这样的方法

getRecommendations(answers: any, vehicles:  Array<string>) {
// map answers to API interface
const apiAnswers = answers.map( answer => {
  return {
    questionId: answer.questionId,
    answer: parseInt(answer.answerKey, 10)
  };
});
const result = {};
result['vehicles'] = vehicles;
result['answers'] = apiAnswers;

return this.http.post(environment.api + '/recommend/', result
).pipe(
  map( (res: any) => {
    return res.Packages;
  }),
  catchError( (err) => {
    this.errorService.showError('Get Recommendation Error');
    return of(`Get Recommendation Error: ${err}`);
  }),
  finalize( () => {
    // hide loader no matter what happens
    this.appLoaderService.setLoading(false);
  })
);
}

我希望此函数发出一个发布请求并返回答案,但是ist确实发出了6个请求。...

我100%确定此方法仅被调用一次,因此我认为是问题所在, 躺在this.http.post方法中的某个地方,但是我不知道是什么问题,有人可以帮助我吗?

编辑:这就是方法的订阅方式

    export class RecommendationsComponent implements AfterViewInit {

  @ViewChildren('packageComponent', { read: ElementRef }) packageElements: QueryList<ElementRef>;

  public translations$: Observable<IResultTranslations>;
  public packages$: Observable<IPackage[]>;
  public recommendedPackages$: Observable<IPackage[]>;
  public optionalPackages$: Observable<IPackage[]>;
  public nonPreferredPackages$: Observable<IPackage[]>;
  public vehicles$: Observable<IVehicle[]>;
  public selectedVehicles: IVehicle[];
  public height: number;

  public selectedPackages: IPackage[] = [];

  constructor(private translate: TranslateService,
    private apiService: ApiService,
    private recommendationService: RecommendationService,
    private router: Router,
    private uiService: UiService,
    private cd: ChangeDetectorRef,
    private translateService: TranslateService,
    private hostService: HostService
  ) {
    const answers = this.recommendationService.getAnswers();
    const vehicles = this.recommendationService.getVehicles();

    // navigate to start if no answers available
    if (!answers || answers.length === 0) {
      this.router.navigate(['']);
      return;
    }

    this.packages$ = this.apiService.getRecommendations(answers, vehicles);
    this.translations$ = this.apiService.getTranslations(answers, vehicles);



    // select recommended packages
    this.packages$ = this.packages$.pipe(
      map( packages => packages.map( p => {
        if (p.recommended) {
          this.toggleSelectedPackage(p, true);
          p.selected = true;
        }
        return p;
      }))
    );

    // filter all recommended packages
    this.recommendedPackages$ = this.packages$.pipe(
      map( packages => packages.filter( p => p.recommended && !p.nonPreferred))
    );

    // filter all optional packages
    this.optionalPackages$ = this.packages$.pipe(
      map( packages => packages.filter( p => !p.recommended && !p.nonPreferred))
    );

    // filter all non preferred packages
    this.nonPreferredPackages$ = this.packages$.pipe(
      map( packages => packages.filter( p => p.nonPreferred))
    );

    // init selectedVehicles
    this.selectedVehicles = [];
    // get vehicles from localized content
    this.vehicles$ = this.translateService.get('vehicles').pipe(
      // filter vehicles with ids from vehicle component
      map(vehiclesArray => vehiclesArray.filter(vehicle => vehicles.indexOf(vehicle.Id) > -1)),
      // add selected flag and toggle function to vehicles
      map(vehiclesArray => vehiclesArray.map(vehicle => {
        vehicle.selected = false;
        vehicle.toggleSelected = () => {
          const selected = (vehiclesArray.filter(selectedVehicle => selectedVehicle.selected === true)).length;
          // don't toggle if it is the last active vehicle
          if ( !vehicle.selected || selected > 1) {
            vehicle.selected = !vehicle.selected;
            this.selectedVehicles = vehiclesArray.filter(selectedVehicle => selectedVehicle.selected);
          }
          return vehicle.selected;
        };
        vehicle.toggleSelected();
        return vehicle;
      }))
    );
  }
  ngAfterViewInit() {

    // synchronize height of package cards after all packages got rendered
    this.packageElements.changes.pipe(
      withLatestFrom(this.packages$),
      map(([change, packages]) => {
        if (packages.length === this.packageElements.toArray().length) {
          return this.uiService.getHeightOfHighestElement(this.packageElements.toArray());
        }
      })
    ).subscribe( (height) => {
        this.height = height;
        this.cd.detectChanges();
    });
  }
}

2 个答案:

答案 0 :(得分:0)

直到有人订阅,才会进行http调用。因此,某些其他方法必须多次调用getRecommendations

该方法运行一次,然后返回尚未订阅的http调用。因此,当您之后订阅this.packages$时,getRecommendations不会再次运行,因为它已经返回。

答案 1 :(得分:0)

供将来参考,这是此处描述的问题 angular-pitfall-multiple-http-requests-with-rxjs-and-observable-async/

  

每个异步管道都会触发一个新的HTTP请求,因为每个结果异步为结果$ Observable创建新的订阅/流。

     

这不是错误,而是实现Observable的方式的本质,以提高灵活性。

     

您可以将Observable result $视为函数声明,并且每个result $ |异步调用相同的函数。