I am expecting only one http request but in my console I am getting multiple http calls. I am not entirely sure the reason. Below is a abbreviated for ease of readability.
component.html
{{ (user | async).firstname }} {{ (user | async).firstname }}
<ul>
<li *ngFor="let profile of (user | async)?.profiles ">
<div>
<p>{{ profile.profileType }}<span *ngIf="isStudent(profile.specialized)"> - {{ profile.specialized }}</span></p>
<p>{{ profile.id }}</p>
</div>
<button class="btn btn-primary float-right" (click)="onGo(profile)">Go</button>
</li>
</ul>
component.ts
private user: Observable<User>;
ngOnInit(){
this.user = this.userDataService.fetchUserDetails(+params['id']);
}
UserDataService.ts
fetchUserDetails(id:number):Observable<User> {
console.log("calls 1 ?"); // this only gets called once!!!
return this.httpClient.get<User>(this.apiUrl + "/" + id)
.pipe(
tap((response) => {
console.log(response); // this is executed multiple times!!!
return response;
}),
catchError( (error) => {
handleIt();
})
)
}
In my console
In my network
What is making HttpClient to make so many http requests? when the UserDataService clearly only been executed once...
http is high level and HttpClient is low level (source) http can make post requests but HttpClient can't (source) both http and HttpClient (with HttpClientRequest ) can make GET and POST requests (source) both http and HttpClient can be used on the client and the server.
How do I stop multiple API calls? On clicking on tabs you interchange state and you use ngOnInit() method every time when a state is changed to get the data.In this way, you can reduce API calls by using nested routing.
The HttpClient is used to perform HTTP requests and it imported form @angular/common/http. The HttpClient is more modern and easy to use the alternative of HTTP. HttpClient is an improved replacement for Http. They expect to deprecate Http in Angular 5 and remove it in a later version.
Every async pipe creates its own subscription to the observable, which ends in seperate API calls. You've got two options to solve it.
Option 1: Work with the as operator to save the result like this:
<ng-container *ngIf="user | async as u">
{{ u.firstname }}
...
</ng-container>
Option 2: Work with the share operator from rxjs:
return this.httpClient.get<User>(this.apiUrl + "/" + id) .pipe(
tap(console.log), // this is executed multiple times!!!
share(),
catchError( (error) => {
handleIt();
})
);
More use of async pipe will affect the efficiency because it will subscribe to every async pipe. You can notice this more if you are calling an HTTP service because it will call the HTTP request for each async pipe.
{{ user.firstname }} {{ user.firstname }}
<ul>
<li *ngFor="let profile of user?.profiles ">
<div>
<p>{{ profile.profileType }}<span *ngIf="isStudent(profile.specialized)"> - {{ profile.specialized }}</span></p>
<p>{{ profile.id }}</p>
</div>
<button class="btn btn-primary float-right" (click)="onGo(profile)">Go</button>
</li>
</ul>
ngOnInit() {
this.userDataService.fetchUserDetails(+params['id']).subscribe(data => this.user = data);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With