简体   繁体   English

RXJS - Angular - 取消订阅主题

[英]RXJS - Angular - unsubscribe from Subjects

As described in this thread , 'official' solution to unsubscribe from Observables in Angular 5+ in general is using takeUntil. 本主题所述 ,在Angular 5+中取消订阅Observables的“官方”解决方案通常是使用takeUntil。 So far, so good. 到现在为止还挺好。 My question is, does this also apply if the Observable I am subscribed to is actually a Subject? 我的问题是,如果我订阅的Observable实际上是一个主题,这是否也适用?

Once you call .subscribe() on anything (Subjects too), something needs to make sure the subscription gets unsubscribed. 一旦你在任何事情上调用.subscribe() (主题也是如此),需要确保订阅被取消订阅。

Dealing with finite Observables : If you subscribe to a finite observable (meaning an observable that has a finite/limited sequence), the last message will send an end signal and the subscription will be canceled automatically. 处理有限Observables :如果您订阅了有限可观察量(意味着具有有限/有限序列的可观察量),则最后一条消息将发送结束信号,并且订阅将自动取消。 Examples of this are: 这方面的例子是:

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

Examples of in finite observables are: 有限观察量的例子是:

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

Calling/piping .first() , .take(number) or .takeWhile(condition that will evaluate to false at some point) or takeUntil(observable that emits a value) on an observable will all turn an otherwise infinite observable into a finite one. 呼叫/管道.first() .take(number).takeWhile(condition that will evaluate to false at some point)takeUntil(observable that emits a value)上可观察到的将全部变为一个无限否则可观察到有限一个。

Stop calling .subscribe() : Another popular method of not having to unsubscribe is by not subscribing in the first place. 停止调用.subscribe() :另一种不必取消订阅的流行方法是首先不订阅。 This might sound stupid, since when would you want an observable that you do not subscribe to? 这可能听起来很愚蠢,因为你什么时候想要一个你不订阅的观察者? Well if you only need to pass some data to your view/html template, piping that observable into the async pipe will pass the unsubscribing issue to the async pipe itself. 好吧,如果您只需要将一些数据传递给您的view / html模板,那么将observable传递到异步管道中会将取消订阅问题传递给异步管道本身。

Typical examples in the html template: 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>

Manually unsubscribing : Lastly, you can choose to keep references to all subscriptions. 手动取消订阅 :最后,您可以选择保留对所有订阅的引用。 You don't have to keep a variable pointing to each subscription, it's easier to just use a single Subscription object to keep track of all the subscriptions, and then unsubscribe to all of them at once. 您不必保留指向每个订阅的变量,只需使用单个Subscription对象来跟踪所有订阅,然后立即取消订阅所有订阅。 Here is an example: 这是一个例子:

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

Quick summerize , how to handle unsubscriptions, any of the below methods: 快速总结 ,如何处理取消订阅,以下任何方法:

  1. Turn infinite observables into finite ones, hereby removing the need to unsubscribe (use .takeUntil(this.destroyed$) and do this.destroyed$.emit() in ngOnDestroy() ). 将无限可观测值转换为有限值,从而无需取消订阅(使用.takeUntil(this.destroyed$)并在this.destroyed$.emit()中执行this.destroyed$.emit() ngOnDestroy() )。
  2. Avoid subscribing, and passing the observable though the async pipe. 避免订阅,并通过async管道传递observable。
  3. Keep a reference to any subscriptions and call .unsubscribe() in the ngOnDestroy() method. 保留对任何订阅的引用,并在ngOnDestroy()方法中调用.unsubscribe()

Personally i tend to only use one of the two first methods. 我个人倾向于只使用两种方法中的一种。

I have something to add. 我有一些要补充的东西。 Subject stores the subscribers internally ( Observable does too). Subject在内部存储订阅者( Observable也是如此)。 If the Subject is part of your component (created inside, stored as property or in a closure) the subject and it's subscriptions are garbage collected with the component itself. 如果Subject是组件的一部分(在内部创建,存储为属性或在闭包中),则主题及其订阅将与组件本身一起进行垃圾收集。

But this is a special case and one should be very careful with it: everything must be contained in the component. 但这是一个特例,应该非常小心:一切都必须包含在组件中。

It is eg safe to not unsubscribe from a FormControl.valueChanges observable if it is used in the component only. 这是如安全不是来自退订FormControl.valueChanges如果仅在组件中使用可观察到的。

But to be on the safe side, and don't want to think about it, just use takeUntil . 但为了安全起见,并且不想考虑它,只需使用takeUntil

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM