【问题标题】:Infinite loop when using *ngFor with async pipe in Angular在Angular中将*ngFor与异步管道一起使用时的无限循环
【发布时间】:2019-10-04 20:21:45
【问题描述】:

我的问题和this one非常相似。

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>

foo.component.ts:

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

fooService 中的fooServiceFunc 一次只会返回一个Observable

我的问题是,现在我的应用程序触发了无限请求(在整个 items 数组被迭代之后,它会从头开始,一遍又一遍地再次触发请求),这似乎是 @987654331 的副作用@管道在this answer中宣布。但我仍然不知道如何解决这个问题?

【问题讨论】:

    标签: javascript angular typescript asynchronous pipe


    【解决方案1】:

    将您共享的流保存到变量并在模板中使用该变量

    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>
    

    现在您为每个 item 创建新流,每个查询运行更改检测,然后再次运行查询。

    我的建议:尽量避免模板中的函数调用,模板中的函数在当前组件的 changeDetection 运行时执行(AsyncPipe 通过输入流中的每个值运行更改检测)。

    【讨论】:

    • 对不起我的英语...如果您需要更多详细信息,我可以给您相关文章。
    • 非常感谢您的回答!我认为您提供参考链接会很好,因为看到这个问题的其他人可能需要这个。而且我发现,由于您的答案中使用了map 语法,data$ 已经迭代了整个items 并且也变成了一个数组。所以,不需要在html模板中使用*ngFor="let item of items",也就是说html中的代码应该是这样的:&lt;ng-container *ngFor="let foo of (data$ | async)"&gt; {{ foo | json }} &lt;/ng-container&gt;
    • 是的,你是对的,我用你的更正更新了答案。
    • 谢谢!顺便问一下,请您提供参考链接吗?我确实想知道更多细节。
    • 要了解为什么在模板内部提取会触发无限循环,首先您需要了解更改检测的工作原理,您可以阅读这篇文章:blog.angular-university.io/…
    猜你喜欢
    • 1970-01-01
    • 2017-05-07
    • 2020-01-15
    • 2017-11-04
    • 2021-09-28
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 2018-04-18
    相关资源
    最近更新 更多