【发布时间】:2017-03-23 18:35:40
【问题描述】:
我有一个带有间隔计时器的 observable,每隔几秒刷新一次数据。这看起来像:
return Observable.interval(2000)
.switchMap(() => this.http.get(this.url)
.map(this.extractData))
“extractData”方法对数据进行了一些处理。另一方面,我有 2 个订阅者。一个人按原样使用数据并将其放入数组中进行显示,例如:
this.myService.getData()
.subscribe(
data => this.data = data,
error => this.errorMessage = <any>error
)
我有另一个订阅者进一步汇总数据以供显示,它看起来像:
this.myService.getData()
.subscribe(
data=> this.summarizeData(data),
error => this.errorMessage = <any>error
)
所有这一切都完美无缺,但在我获得大量记录(列表随着时间的推移而增长)后,比如大约 1000 条,我注意到 UI 冻结了很长一段时间。是的,我知道我可以将列表大小保持在一个较小的数字,但现在我想看看我是否可以用这个更大的数据集来解决它。
所以我查看了其他帖子,并在answer to this post 上发现了一个有趣的方法,并通过向显示器发送一个可观察对象并使用异步管道进行了尝试。我几乎得到了相同的结果,即每隔几秒 UI 就会冻结一小段时间。
对于首选哪种方法有什么建议吗?所有示例都像我正在做的那样在组件中添加订阅。那么,关于如何防止 UI 冻结的任何建议?
更新:根据@Nicolas,我已经研究过使用 Angular Zones 让 http get 在 Angular 的区域之外运行(这似乎是瓶颈,因为每个订阅似乎导致它需要大约 200-400 毫秒取决于记录的数量)。所以也许我不太了解如何以一种有用的方式使这项工作(我可以使它工作,但它似乎没有帮助,这让我觉得我做错了什么)。
如果我理解正确,我会使用“runOutsideAngular”方法在 Angular 区域之外运行一些代码。然后使用“运行”将事物分配回 Angular 区域,以便更改检测可以工作并更新显示。
所以我尝试在 Observable 端和 Subscriber 端都做一些事情。但是,就像我说的那样,似乎都没有帮助。任何指向正确方向的指针都会有所帮助!
可观察的结束:
return Observable.interval(2000)
.switchMap(() => this.doGet());
private doGet(): ObservableInput<any> {
return this.zone.runOutsideAngular(() => {
return this.http.get(this.url).map(this.extractData).catch(this.handleError);
});
}
订阅方:
this.zone.runOutsideAngular(() => {
this.myService.getData()
.subscribe(
data => {
this.zone.run(() => this.data = data)
},
error => this.errorMessage = <any>error
)
});
【问题讨论】: