当我使用Observable.Interval
执行UI的http刷新时,如果间隔过快,它会锁定UI上的按钮。按钮没有注册点击,似乎是一个时间问题。如果我增加时间并因此错过了get调用按钮,则数据会在更新时延迟。
间隔
this.dataSub = Observable.interval(1000).subscribe(x => {
this.getData();
})
的getData
getData(): void {
this.dataService.getData()
.subscribe(
data => this.data = data,
error => console.log("Error HTTP Get Service" + this.data),
() => {});
}
是否有最佳做法,或者我错过了我应该做的事情来刷新用户界面而不是锁定按钮
答案 0 :(得分:7)
通常,您应该尽可能避免明确订阅observable。相反,使用所有运算符(是的,找出正确的运算符可能非常棘手)可以将所有源/输入可观察量组合成一个或多个在async
管道视图中使用的可观察对象
不要忘记JS是单线程的(除了工作者)。您的UI和大多数Angular代码必须共享一个线程,因此长时间运行的JS会锁定您的UI。
这有三个主要好处:
ngOnDestroy()
挂钩中取消订阅,或者当您不再关心它时,则无论何时手动订阅都可能会造成内存泄漏。当async
管道在使用它的组件/元素被破坏时会正确取消订阅 - 您无需担心它。switchMap()
,switchLatest()
等运算符,您可以取消和清除超级HTTP调用和其他昂贵的操作,甚至可以在它们启动之前停止它们(如果不再需要它们)。不要做比你必须做的更多。这通常意味着更改检测不必运行太多,这意味着更好的性能。考虑到所有这些,您如何将其应用于您的代码?
你可能没有注意到的一件事(很多人不是),如果你的DataService.getData()
方法是这样的话:
getData(): Observable<MyData[]> {
return this.http.get('http://some.url/data').map(res => res.json());
}
然后每次订阅Http
服务创建的observable时,都会发出新请求。这就是你想要的,但你不希望想要的是在新的请求发布后立即处理任何先前请求的结果。
所以你可以在控制器中使用类似的东西,用最近的请求中的最新数据组成一个observable:
ngOnInit() {
// (I follow a convention where observable properties end in $)
this.data$ = Observable.interval(1000).flatMapLatest(() => {
return this.dataService.getData();
});
}
没有订阅,只是一个已创建的observable。然后在您的视图中,只使用具有data$
属性的异步管道,您就是金色。
例如:
<ul *ngFor="let d of (data$ | async); trackBy: d?.id">
<li>{{d.name}}</li>
</ul>