funkid
funkid

Reputation: 665

Infinite loop when using *ngFor with async pipe in Angular

My problem is very similar to this one.

In foo.component.html:

<ng-container *ngFor="let item of items">
    <ng-container *ngIf="(fooFunc(item.property) | async) as element">
        {{ element | json }}
    </ng-container>
</ng-container>

In foo.component.ts:

fooFunc(foo: any) {
  return this.fooService.fooServiceFunc(foo).pipe(
    take(1),
    shareReplay(1)
  );
}

The fooServiceFunc in fooService will return only one Observable at one time.

My problem is that now my app fires infinite requests (after the whole items array has been iterated, it will fire the request again from beginning, over and over), which seems to be a side-effect of async pipe which is announced in this answer. But I still cannot figure out how to fix this?

Upvotes: 3

Views: 4089

Answers (1)

izmaylovdev
izmaylovdev

Reputation: 1880

Save you shared stream to variable and use the variable in template

data$ = forkJoin(
  this.items.map(item => this.fooService.fooServiceFunc(item.property).pipe(
    map(fetchResult => ({ fetchResult, item })
  ))
)
<ng-container *ngFor="let item of data$ | async">
    <ng-container *ngIf="item.fetchResults">
        {{ item.fetchResults | json }}
    </ng-container>
</ng-container>

Now you create new stream for each item, and each query runs change detection, whitch runs queries again.

My advice: Try to avoid function calls in templates, functions in template executes when changeDetection for current component runs (AsyncPipe run change detection by each value in the input stream).

Upvotes: 3

Related Questions