RXJS - Angular - 取消订阅主题

时间:2018-05-31 17:01:24

标签: angular rxjs observable subject

正如this thread所述,'官方'解决方案是取消订阅Angular 5+中的Observable一般使用takeUntil。到现在为止还挺好。我的问题是,如果我订阅的Observable实际上是一个主题,这也适用吗?

2 个答案:

答案 0 :(得分:7)

一旦你在任何事情上调用.subscribe()(主题也是如此),需要确保订阅被取消订阅。

处理有限的Observables : 如果您订阅了有限可观察量(意味着具有有限/有限序列的可观察量),则最后一条消息将发送结束信号,并且订阅将自动取消。 例如:

Observable.of(100)
Observable.from([1,2,3,4])

in 有限可观察量的例子是:

Observable.fromEvent(document, 'click')
Observable.timer(1000)

在一个可观察者上呼叫/管道.first().take(number).takeWhile(condition that will evaluate to false at some point)takeUntil(observable that emits a value)都会将无限的可观察量转变为有限的观察者。

停止调用.subscribe(): 另一种不必取消订阅的流行方法是首先不订阅。这可能听起来很愚蠢,因为你什么时候想要一个你不订阅的观察者?好吧,如果您只需要将一些数据传递给您的view / html模板,那么将observable传递到异步管道中会将取消订阅问题传递给异步管道本身。

html模板中的典型示例:

<h1>Editing {{ infiniteObservable$ | async }}<h1>
<li *ngFor="let user of userObservable$ | async as users; index as i; first as isFirst">
   {{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span>
</li>

手动取消订阅:最后,您可以选择保留对所有订阅的引用。您不必保留指向每个订阅的变量,只需使用单个订阅对象来跟踪所有订阅,然后立即取消订阅所有订阅。 这是一个例子:

const subscriptions = new Subscription();
subscriptions.add(observable1$.subscribe());
subscriptions.add(observable2$.subscribe());
subscriptions.unsubscribe();

快速摘要,如何处理取消订阅,以下任何一种方法:

  1. 将无限的可观察量转换为有限的,因此无需取消订阅(在.takeUntil(this.destroyed$)中使用this.destroyed$.emit()ngOnDestroy())。
  2. 避免订阅,并通过async管道传递observable。
  3. 保留对所有订阅的引用,并使用.unsubscribe()方法致电ngOnDestroy()
  4. 我个人倾向于只使用前两种方法中的一种。

答案 1 :(得分:0)

我要添加一些内容。 Subject在内部存储订户(Observable也在内部)。如果Subject是组件的一部分(在内部创建,存储为属性或在闭包中),则主题及其预订将随组件本身一起被垃圾回收。

但这是一种特殊情况,应该非常小心:所有内容都必须包含在组件中。

例如如果仅在组件中使用,则可以取消订阅FormControl.valueChanges

但是为了安全起见,不想考虑它,只需使用takeUntil