大家好,我正在尝试通过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();
});
}
}
答案 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 $ |异步调用相同的函数。