我有以下组件模板:
<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<Date>
的简单方法:
public getNext(deadline: string): Observable<Date> {
return this.http.get<Date>(`${this.config.apiEndpoint}/api/meeting?deadline=${deadline}`);
}
我的目标是调用该方法并使用模板中的异步管道订阅observable。但是,当我运行应用程序时,会生成无限的GET和OPTIONS请求。
此外,如果我将方法调用放在ng之外,同样的事情也会发生。调用需要在ngFor内执行,因为每个集合项的参数都不同。
为什么简单地调用该方法一次,订阅后不再生成调用?
答案 0 :(得分:4)
在模板中调用函数通常不是一个好主意,因为它会导致不可预测的结果。这是您重构代码以避免这种情况的方法:
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>
这是我创建的stackblitz,您可以在其中看到类似机制的工作原理:https://stackblitz.com/edit/angular-nyn4qz
答案 1 :(得分:3)
肯定你的问题与变化检测有关。
每次角度考虑可以对绘制模板所需的内容进行更改(即,除非您的组件为OnPush
,否则任何时候都有浏览器事件),它将重新绘制组件,从而重新触发循环和可观察的。
在这种情况下,您有两种选择:
OnPush
ChangeDetectionStrategy
),但只有当@Input()
有限的ngOnInit
时,它才会起作用触发组件的更新。ngOnChanges
或data
中执行请求(在@Input()
是您的组件 middle = lowerIndex + (higherIndex - lowerIndex) / 2;
= 0 + (7 - 0) / 2
= 0 + 7 / 2
= 3. //remember the truncation in int.
的情况下),并将结果存储在您的数组中以你的模板为基础进行for循环(我会这样做)。答案 2 :(得分:3)
Angular在每个事件周期调用getNext
,每次getNext
发出新的http
请求并返回新的Observable
。您需要从第一个函数调用中缓存Observable
。我建议你在控制器的某个地方创建它们,然后将模板作为变量传递。