2016-07-28 73 views
9

我想可能会继续订阅观察者并忘记取消订阅。我怀疑这是发生在我的应用程序中。观察者是否拥有一个可以让我计算用户数量的属性?在angular2中,是否有可能获得可观察用户的计数?

+1

我认为最接近你可以得到的是使用.refCount()。 https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/refcount.md –

+0

我根据你的描述回答了你希望有方法不要忘记取消订阅,因为我觉得它是你问题的核心。当然有一些方法可以编写一个实际上有助于计算的运算符,但由于不同运营商可能在流的不同点上订阅的方式等因素,这会非常复杂。希望我的回答能够为您提供所需的工具,而无需进入可观察的用户数量的元信息。 –

回答

8

虽然绝对有可能忘记取消订阅,并且泄漏的后果从永无止境的测试运行者到内存泄漏,但angular2拥有一些工具和通用模式来管理其生命周期。

angular2提供了一种不会忘记的简单方法。在模板中使用最简单的方法是简单地使用异步管道,该管道将自动为您订阅和取消订阅。

否则,当您使用.subscribe()方法时,它会返回订阅。通常的做法是在构造函数中捕获注入的依赖关系,对ngOnInit中的组件进行必要的订阅,并取消订阅ngOnDestroy

有时候,你会订阅多个观察对象。 RxJS将类Rx.Subscription提供给组订阅。它可以通过以下方式使用:

const incomeSubscription = income$.subscribe(x => console.log(x)); 
const expensesSubscription = expenses$.subscribe(x => console.log(x)); 

const subscription = new Rx.Subscription(); 
subscription.add(incomeSubscription); 
subscription.add(expensesSubscription); 

现在呼吁subscription.unsubscribe()将取消任何订阅仍然有效。

最后,理解RxJS流默认是单播是​​非常重要的(不像承诺总是缓存结果并且只是多播)。这意味着在实践中,每个订阅实际上成为一个新的rx流。在例如Http.get()等“冷”可观察的情况下,每个订阅实际上将从头开始生成数据。因此,在Http.get()提到的情况下,您将为每个订阅(或在模板中使用管道异步的实例)进行HTTP调用。

这意味着它是很好的做法:

  • 仅使用异步管道在容器风格组件,以及有什么都不知道RxJS的哑 表象成分。这有助于 仅在容器级别

  • 订阅如果用户之间共享数据使用像.refCount运营商() 在其他一些情况下,或主题。这使得流播 和用户分享,而不是每个人都有相同的流自己的

+1

使用角度v4,已经成为使用'|的好实践async'结合'as secondaryName'(stream $ | async as streamData),所以在容器组件中,如果多次使用observable的值,则不会多次订阅observable。 –

+0

行为(可能的内存泄漏是由过多的订阅引起的)对于Angular 5.x.x来说是否一样? –

0

我有这个问题,我通过建立订阅数组解决了这个问题:每次

import { Subscription } from 'rxjs/Rx'; 

private subValueChanges: Array<Subscription>; 

然后我订阅,推入阵列:

this.subValueChanges.push(
    this.someControl.valueChanges 
     .debounceTime(1000) 
     .distinctUntilChanged() 
     .takeUntil(this.destroyValueChanges$) 
     .subscribe (newValue => {...} 
); 

然后你知道数组的长度是'someControl'有多少用户。

我不推荐它作为解决方案,但有边缘情况下,这可能是有用的(我有一个)。

另外有趣的是订阅有一个标志“关闭”属性,你可以检查 - 如果它关闭,例如,你可以从数组中删除它。或者,当您首次订阅时,请设置onunsubscribe事件以从阵列中删除该特定订户。无论哪种方式,那么你的数组将只包含活跃的监听器 - 所以它的长度总是告诉你他们有多少人在那里! :)