Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using async pipe in template causes multiple requests in Angular 11

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:

  1. Multiple identical async pipe in Angular causing multiple http requests
  2. How can I prevent the Angular async pipe from making frequent server calls when no results come back?

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.

like image 331
RRGT19 Avatar asked Feb 27 '26 00:02

RRGT19


1 Answers

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

like image 189
andriishupta Avatar answered Feb 28 '26 14:02

andriishupta