RXJS - Angular - unsubscribe from Subjects

僤鯓⒐⒋嵵緔 提交于 2019-12-13 13:22:40

问题


As described in this thread, 'official' solution to unsubscribe from Observables in Angular 5+ in general is using takeUntil. So far, so good. My question is, does this also apply if the Observable I am subscribed to is actually a Subject?


回答1:


Once you call .subscribe() on anything (Subjects too), something needs to make sure the subscription gets unsubscribed.

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. Examples of this are:

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

Examples of infinite 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.

Stop calling .subscribe(): Another popular method of not having to unsubscribe is by not subscribing in the first place. 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.

Typical examples in the html template:

<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. 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()).
  2. Avoid subscribing, and passing the observable though the async pipe.
  3. Keep a reference to any subscriptions and call .unsubscribe() in the ngOnDestroy() method.

Personally i tend to only use one of the two first methods.




回答2:


I have something to add. Subject stores the subscribers internally (Observable does too). 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.

But this is a special case and one should be very careful with it: everything must be contained in the component.

It is e.g. safe to not unsubscribe from a FormControl.valueChanges observable if it is used in the component only.

But to be on the safe side, and don't want to think about it, just use takeUntil.



来源:https://stackoverflow.com/questions/50629357/rxjs-angular-unsubscribe-from-subjects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!