3

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?

1 Answer 1

3

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).

Sign up to request clarification or add additional context in comments.

7 Comments

Sorry for my English... I can give you relevant articles if you need more details.
Very appericiate for your answer! I think it will be nice for you to provide the reference link since others who see this question may need this. And I found that, since the map syntax used in your answer, the data$ has already iterate the whole items and becomes an array, too. So, there is no need to use *ngFor="let item of items" in html template, which means the code in html should be things like this: <ng-container *ngFor="let foo of (data$ | async)"> {{ foo | json }} </ng-container>
yes you're right, I updated answer with your corrections.
Thanks! By the way, would you please give out the reference links? I do want to know more details.
for understand why fetch inside of template triggers infinity loop, first at all you need to understand how change detection works, you can read this article for that: blog.angular-university.io/…
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.