I am curious on how am I suppose to unsubscribe all my subscriptions. I knew about the takeWhile() and takeUntil(). I find the takeUntil() more usable for me.
as far as I understand, takeWhile() take effects after we get the data. then unsubscribe until the component is destroy.
Whats is the difference of using takeUntil() and not using it. just .unsubscribe()?
without using takeUntil()
ngOnInit() {
this.subscriptions = this._membersService.getMembers().subscribe(data =>
this.members = data)
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
using takeUntil
private destroyed$: Subject<{}> = new Subject();
ngOnInit() {
this._membersService.getMembers().takeUntil(this.destroyed$).subscribe(data
=> this.members = data)
}
ngOnDestroy() {
this.destroyed$.next();
}
also how can I determine If I unsubscribe successfully?
Specifically, we must unsubscribe before Angular destroys the component. Failure to do so could create a memory leak. We unsubscribe from our Observable in the ngOnDestroy method.
They all have complete() method, so if you call that method, even if you had 100 subscriptions, they will all unsubscribed automatically.
Just keep in mind that take(1) still doesn't unsubscribe when component is being destroyed. The subscription remains active until first value is emitted no matter if component is active or destroyed.
🎩 Automagically Unsubscribe in Angular As you probably know when you subscribe to an observable or event in JavaScript, you usually need to unsubscribe at a certain point to release memory in the system. Otherwise, you will have a memory leak. A memory leak occurs when a section of memory that is no longer being…
The main difference is the way of thinking... and the boilerplate.
Without takeUntil
, when your file will grow in size and lines of code, you might end up with something like that:
private subscription1: Subscription;
private subscription2: Subscription;
private subscription3: Subscription;
private subscription4: Subscription;
private subscription5: Subscription;
private subscription6: Subscription;
ngOnInit() {
this.subscription1 = this.service.method().subscribe(...);
this.subscription2 = this.service.method().subscribe(...);
this.subscription3 = this.service.method().subscribe(...);
this.subscription4 = this.service.method().subscribe(...);
this.subscription5 = this.service.method().subscribe(...);
this.subscription6 = this.service.method().subscribe(...);
}
ngOnDestroy() {
this.subscription1.unsubscribe();
this.subscription2.unsubscribe();
this.subscription3.unsubscribe();
this.subscription4.unsubscribe();
this.subscription5.unsubscribe();
this.subscription6.unsubscribe();
}
Or, you might declare an array of subscriptions and push into it.
Both doesn't seem to be very handy and if you end up with many methods, containing subscriptions, you won't be able to see whether they're being unsubscribed or not if you don't scroll to the ngOnDestroy
.
On the other hand, using a Subject
is much more readable:
private onDestroy$ = new Subject<void>();
ngOnInit() {
this.service.method().takeUntil(this.onDestroy$).subscribe(...);
this.service.method().takeUntil(this.onDestroy$).subscribe(...);
this.service.method().takeUntil(this.onDestroy$).subscribe(...);
this.service.method().takeUntil(this.onDestroy$).subscribe(...);
this.service.method().takeUntil(this.onDestroy$).subscribe(...);
this.service.method().takeUntil(this.onDestroy$).subscribe(...);
}
ngOnDestroy() {
this.onDestroy$.next();
this.onDestroy$.complete();
}
Even if subscriptions are divided across the whole file, you can just check whether takeUntil(this.onDestroy$)
is present or not.
It's also closer to the idea of Rxjs and dealing with streams.
Now, to make sure something is being unsubscribed, you can just use the third argument of subscribe:
this.service.method().takeUntil(this.onDestroy$).subscribe(
onNext => ...,
onError => ...,
onComplete => console.log('stream has been completed')
);
If you don't like to put anything into the subscribe method, you could do that:
this.service.method().takeUntil(this.onDestroy$)
.do({
complete => console.log('stream has been completed')
})
.subscribe();
If you want to go further down the subject, you should read this excellent article by Ben Lesh: https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87
The recommended way is to use RxJS operators such as takeUntil() operator as is explained by @maxime1992, but takeUntil() isn't the only operator for the job you can use other RxJS operators as well for example takeWhile(), first(), elementAt(), etc. You can find a detailed explanation here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With