Angular 2 Observable Interval锁定用户界面 [英] Angular 2 Observable Interval locks out UI

查看:107
本文介绍了Angular 2 Observable Interval锁定用户界面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用Observable.Interval执行UI的http刷新时,如果间隔太快,它将锁定UI上的按钮,使其无法工作.这些按钮没有记录点击,这似乎是一个计时问题.如果我增加了时间安排,因此错过了get调用,那么按钮会起作用,但是数据随后会延迟更新.

When I use a Observable.Interval to perform a http refresh of a UI it locks out the buttons on the UI from working if the interval is too fast. The buttons do not register the click, seems to be a timing issue. If I increase the timing and therefore miss the get call the buttons work, but the data is then delayed in updating.

间隔

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),
              () => {});
 }

有没有最佳实践,或者我缺少一些应该刷新界面但不锁定按钮的事情

Is there a best practice, or something I'm missing that I should be doing to refresh the UI but not lock out the buttons

推荐答案

理论

通常,应尽可能避免显式订阅可观察对象.取而代之的是,使用所有可用的运算符(是的,要找出正确的运算符会非常棘手),以将所有源/输入可观察值组合为一个或多个可观察的对象,您可以在async管道的视图中使用该<

The theory

In general, you should avoid explicitly subscribing to observables wherever possible. Instead, use all of the operators (yes, it can be very tricky to figure out the right ones) available to compose all the source/input observables into one or more observables that you use in the view with the async pipe.

别忘了JS是单线程的(工人除外).您的UI和大多数Angular代码必须共享一个线程,因此长时间运行的JS会锁定您的UI.

Don't forget that JS is single threaded (aside from workers). Your UI and most Angular code has to share the one thread, so long running JS locks up your UI.

这有三个主要好处:

  1. 几乎不可能导致内存泄漏.如果您不记得总是退订ngOnDestroy()钩子,或者当您不再关心它时,每当您手动订阅时,都有可能造成内存泄漏.而async管道在使用它的组件/元素被销毁时将正确取消订阅-您无需担心.
  2. 减少工作量.使用switchMap()switchLatest()等运算符,您可以取消和清除取代的HTTP调用和其他昂贵的操作,或者如果不再需要它们,甚至可以在启动之前将其停止.不要做比您必须做的更多的事情.这通常也意味着更改检测不必运行太多,这意味着更好的性能.
  3. 更干净的代码.成员变量更少,功能更多的代码.是的,在学习Rx时可能会有点难以理解,但会变得更容易.
  1. It's almost impossible to cause memory leaks. If you don't remember to always unsubscribe in the ngOnDestroy() hook or when you no longer care about it, you risk creating a memory leak whenever you manually subscribe. Whereas the async pipe will unsubscribe correctly when the component/element it is used on gets destroyed - you don't need to worry about it.
  2. Doing less work. Using operators like switchMap(), switchLatest(), etc, you can cancel and cleanup superceded HTTP calls and other expensive operations, or even stop them before they have started if they are no longer required. Don't do more than you have to. This also usually means the change detection doesn't have to run as much, which means better performance.
  3. Cleaner code. Less member variables, more functional-like code. Yes, it can be a little harder to understand when you are learning Rx, but it gets easier.

实践中

牢记所有这些,如何将其应用于代码?

In practice

With all that in mind, how could you apply it to your code?

您可能不知道(很多人都不知道)的一件事是,如果您的DataService.getData()方法类似于:

One thing you may not be aware of (many people aren't) is that if your DataService.getData() method is something like:

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

然后,每次您订阅由Http服务创建的可观察对象时,都会发出一个新请求.这就是您想要的,但是,您不需要的目的是,在提出新请求后立即处理以前的任何请求的结果.

then every time you subscribe to the observable created by the Http service, a new request is made. This is what you want, but what you don't want is to process the results from any previous requests as soon as a new one is made.

因此,您可以使用控制器中的类似内容,用最近请求中的最新数据组成一个可观察值:

So you could instead just compose one observable with the latest data from the most recent request using something like this in your controller:

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

没有订阅,只是一个可观察的对象.然后,在您的视图中,只需将异步管道与data$属性一起使用,您便会很高兴.

No subscriptions, just a created observable. Then in your view, just use the async pipe with the data$ property and you are golden.

例如:

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

这篇关于Angular 2 Observable Interval锁定用户界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆