I'm doing a web application in Angular v11.0.2. I need to do a HTTP call to show some information on screen. To save time and to take advantage of the async pipe benefits, I'm using it in the template, but, it's causing multiple requests that never stops.
Service
export class MyDataService {
constructor(
private http: HttpClient,
) {
}
fetchMyEmployeeData(): Observable<any[]> {
return this.http.post<any[]>('ENDPOINT', {});
}
}
Component
export class MyAwesomeComponent {
constructor(
public myDataService: MyDataService,
) {
}
}
Template
<ng-container *ngIf="(myDataService.fetchMyEmployeeData() | async) as data">
</ng-container>
This causes multiple requests and never stops.
The same happens if I use *ngFor:
<tr *ngFor="let d of (myDataService.fetchMyEmployeeData() | async)">
<td>.</td>
</tr>
I have tried the following this:
Using the shareReplay operator:
fetchMyEmployeeData(): Observable<any[]> {
return this.http.post<any[]>('ENDPOINT', {}).pipe(shareReplay());
}
Using a simple div:
<div *ngIf="(myDataService.fetchMyEmployeeData() | async) as data">
</div>
I know that if I subscribe from the component and save the results in a local variable, I can call it in the template, but this is not my goal. Working example:
export class MyAwesomeComponent implements OnInit {
data: any[];
constructor(
public myDataService: MyDataService
) {
}
ngOnInit() {
// This is not my goal because I will need to handle the subscription life manually.
this.myDataService.fetchMyEmployeeData().subscribe(res => this.data = res);
}
}
I have also followed the recommendations given here:
I don't know exactly what causes this multiple requests and how can I avoid it.
My goal is to use the async pipe in the template and do just one HTTP call.
UPDATE: shareReplay is needed if you call variable multiple times in template, misunderstand the question.
shareReplay() should be on component level, cause when you call the fetchMyEmployeeData() it is a function that returns new Observables(and new shareReplays for each)
in component create:
employeeData$ = this.myDataService.fetchMyEmployeeData().pipe(shareReplay());
and use in template as
employeeData$ | async
in this case, it would do only a single request for back-end
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