【问题标题】:Async Pipe in Template inside ngFor block triggers http GET calls loopngFor 块内模板中的异步管道触发 http GET 调用循环
【发布时间】:2018-07-26 13:11:58
【问题描述】:

我有以下组件模板:

<div *ngFor="let ctrl of data; trackBy:ctrl?.Id">
   <div *ngIf="getNext(ctrl.nextDate) | async as next">
        <span>{{next | date: 'dd.MM.yyyy'}}</span>
   </div>
</div>

getNext() 是一个返回Observable&lt;Date&gt; 的简单方法:

public getNext(deadline: string): Observable<Date> {
   return this.http.get<Date>(`${this.config.apiEndpoint}/api/meeting?deadline=${deadline}`);
}

我的目标是调用该方法并使用模板中的异步管道订阅 observable。但是,当我运行应用程序时,会生成无休止的 GET 和 OPTIONS 请求。

另外,如果我将方法调用放在 ngFor 之外,也会发生同样的情况。由于每个集合项的参数不同,因此需要在 ngFor 内部执行调用。

为什么方法只调用一次,订阅后就不再产生调用?

【问题讨论】:

    标签: angular typescript observable rxjs5


    【解决方案1】:

    在模板中调用函数通常不是一个好主意,因为它会导致不可预测的结果。您可以通过以下方式重组代码以避免这种情况:

    data: any = [....] // some data
    data$: Observable[];
    
    ngOnInit() {
        this.data$ = this.data.map(elem => this.getNext(elem));
    } 
    
    public getNext(deadline: string): Observable<Date> {
       return this.http.get<Date>(`${this.config.apiEndpoint}/api/meeting?deadline=${deadline}`);
    }
    

    在你的模板中:

    <div *ngFor="let ctrl of data$">
       <div *ngIf="ctrl | async as next">
            <span>{{next | date: 'dd.MM.yyyy'}}</span>
       </div>
    </div>
    

    这是我创建的堆栈闪电战,您可以在其中看到类似机制的工作原理:https://stackblitz.com/edit/angular-nyn4qz

    【讨论】:

    • “在模板中调用函数通常不是一个好主意,因为它会导致不可预测的结果。” - 什么是不可预测结果的示例?
    • @Zze 一个不可预知的结果就是例如问题中的问题:)
    • 大声笑,正是:D
    • @VictorNoël 正如您的回答中所解释的那样,这并非不可预测。尽管不幸的是,它的工作方式与预期的完全一样 - 导致此问题的循环变化检测。虽然这是公认的答案,但在这个答案中,首先没有解释实际问题是什么。
    • @Zze 你是对的,这是不可预测的,因为它永远不会像在模板中使用函数的开发人员所期望的那样。无论如何,感谢您的信任投票!
    【解决方案2】:

    Angular 在每个事件循环中调用getNext,并且每次getNext 发出新的http 请求并返回新的Observable。您需要从第一个函数调用中缓存Observable。我建议您在控制器中的某处创建它们,然后将模板作为变量传递。

    【讨论】:

      【解决方案3】:

      您的问题肯定与变更检测有关。

      每当 angular 认为绘制模板所需的内容可能会发生变化(即,只要有浏览器事件,除非您的组件是 OnPush),它都会重新绘制组件,从而重新触发循环和 observable .

      在这种情况下,您有两个选择:

      • 确保在不需要时不会触发更改检测(例如,通过使您的组件遵循OnPushChangeDetectionStrategy),但它主要仅在触发组件更新的@Input() 的有限集合时才有效.
      • 只在ngOnInitngOnChanges 中执行一次请求(如果data 是您的组件的@Input()),并将结果存储在一个数组中,您的模板基于该数组执行循环(我会走这条路)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-04
        • 2019-07-31
        • 2020-11-07
        • 1970-01-01
        • 2016-02-18
        • 2019-10-04
        • 2017-12-14
        • 1970-01-01
        相关资源
        最近更新 更多