Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Subject.complete() unsubscribe all listeners?

I build a simple confirmation dialog service (Angular 2) with this method:

confirm(body?: string, title?: string): Subject<void> {     this.confirmation = new Subject<void>();     // ... show dialog here... "are you sure?"     return this.confirmation; }  _onYesClicked() {   // ... closing the dialog   this.confirmation.next();   this.confirmation.complete(); }   _onNoClicked() {   // ... closing the dialog   this.confirmation.complete(); } 

Usage:

confirmationService.confirm().subscribe(() => alert("CONFIRMED")); 

If someone uses the service, he gets a Subject (which is an Observable) returned and can "subscribe()" to it. The subscription is called when "yes" is clicked and therefore the confirmation was given...

Is this the correct way to do this? And more important... will the call to

this.confirmation.complete(); 

unsubscribe the subscribed listeners and therefore prevent any lingering references (memory leakage)?

like image 437
Wolfgang Avatar asked Nov 06 '16 18:11

Wolfgang


People also ask

Does Observable complete unsubscribe?

In these cases, the observable will call . complete() after it has emitted all of it's values. There's no need to unsubscribe. It completes on it's own, which means it unsubscribes all subscribers automatically.

Do I need to unsubscribe from a completed Observable RxJS?

Yes you are correct. After a stream is terminated ( onComplete / onError has been called ), subscriber unsubscribes automatically. You should be able to test these behaviors using isUnsubscribed() method on the Subscription object.

Does RxJS take unsubscribe?

Unsubscribing Manually RxJS provides us with a convenient method to do this. It lives on the Subscription object and is simply called . unsubscribe() .


1 Answers

If you want to be sure it removes all Observers you can check it for yourself in https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L91. It calls complete() on all Observers (Observers are typically just dumb objects implementing Observer interface) and then sets this.observers.length = 0;. So the answer is yes.

Your approach is valid, it's basically the same as Angular2 regularly does with EventEmitter. Just one thing you can improve is start using asObservable() when exposing Subjects. This will hide the fact that you're using a Subject underneath and return just a regular Observable. This way you don't let your users to by accident (or from misunderstanding) try to call next() , complete() or error() on your Subject.

Regarding memory leakage, this has to be handled by RxJS, so you shouldn't worry about it and if there's a problem the authors would probably notice it before you.

Also have a look at this: Observable vs Subject and asObservable

like image 152
martin Avatar answered Sep 24 '22 15:09

martin