Angular 2 Observable Interval locks out UI



当我使用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),
() => {});
}

有没有一个最佳实践,或者我错过了什么,我应该做刷新UI,但不锁定按钮

理论

一般来说,您应该尽可能避免显式订阅可观察性。相反,使用所有可用的运算符(是的,要找出正确的运算符可能非常困难)将所有源/输入可观察器组合为一个或多个可观察性,您可以在具有async管道的视图中使用它们。

不要忘记JS是单线程的(除了worker)。你的UI和大多数Angular代码必须共享一个线程,所以只要运行JS就会锁定你的UI。

这有三个主要好处:

  1. 几乎不可能导致内存泄漏。如果你不记得总是在ngOnDestroy()挂钩中取消订阅,或者当你不再关心它时,你就有可能在手动订阅时造成内存泄漏。而async管道在其使用的组件/元素被销毁时将正确取消订阅,您不必担心
  2. 少做工作。使用switchMap()switchLatest()等运算符,您可以取消和清除被取代的HTTP调用和其他昂贵的操作,如果不再需要,甚至可以在它们开始之前停止它们。不要做得太多。这通常也意味着更改检测不必运行那么多,这意味着性能更好
  3. 清洁器代码。更少的成员变量,更像函数的代码。是的,当你学习Rx时,可能会有点难以理解,但它会变得更容易

在实践中

考虑到所有这些,您如何将其应用于您的代码?

有一件事你可能没有意识到(很多人没有意识到),如果你的DataService.getData()方法是这样的:

getData(): Observable<MyData[]> {
return this.http.get('http://some.url/data').map(res => res.json());
}

然后,每次订阅Http服务创建的observable时,都会发出一个新的请求。这是您想要的,但您不想要的是在发出新请求后立即处理任何以前请求的结果。

因此,你可以在你的控制器中使用这样的东西,用最近请求的最新数据组成一个可观察的:

ngOnInit() {
// (I follow a convention where observable properties end in $)
this.data$ = Observable.interval(1000).flatMapLatest(() => {
return this.dataService.getData();
});
}

没有订阅,只有一个创建的可观察对象。然后,在您的视图中,只需使用带有data$属性的异步管道,您就可以获得金牌。

例如:

<ul *ngFor="let d of (data$ | async); trackBy: d?.id">
<li>{{d.name}}</li>
</ul>

最新更新