I've been looking around for a simple way to avoid the memory leaks I've read about caused by failing to unsubscribe. Most of the time I'm just wanting the ONE response from my backend. And then I'll want to unsubscribe. So why not call it in the callback?
onSubmit(){
var subscription = this.puzzleService.login(this.nameoremail, this.password).subscribe( success =>{
if(success){
this.router.navigate(['/puzzles']);
}
else{
this.message="Login failed. Please try again.";
}
this.loading=false;
subscription.unsubscribe();
});
this.loading=true;
}
Note the assignment of the subscription to a local variable. This local variable is then locked inside a closure and told to unsubscribe when its work is done. No class variables, no takeUntil, nothing else.
It compiles and runs without error. I'm not familiar enough with the debugger to determine if the observable object is actually destroyed and subsequently garbage collected.
Is there something I'm missing? Can someone more familiar with the debugger correct me? Because if this works I'm going to be doing this everywhere. Except in my pollWords() function...
This seems much simpler than other solutions I've seen advocated. I'd think I didn't even really need the closure, as when I look at it in the debugger I see "_this" is the closure for "this" and "this" is actually the observable. So if there was some way to prevent the munging that is happening to "this" then I could call "this.unsubscribe()" and be done. Not that an object reference closure is a horrible thing...
References:
Angular/RxJs When should I unsubscribe from `Subscription`
Rxjs Observable Lifecycle
We can simply call the unsubscribe() method from the Subscription object returned by the subscribe() method in the ngOnDestroy() life-cycle method of the component to unsubscribe from the Observable. There is also a better way to unsubscribe from or complete Observables by using the takeUntil() operator.
Note that when an observable emits a complete event, subscriptions will automatically be unsubscribed, and that certain frameworks using RxJS may also handle unsubscriptions automatically in certain cases. In all other cases, we must handle unsubscribing ourselves.
The RxJS first() operator waits until the first value is emitted from an observable and then automatically unsubscribes, so there is no need to explicitly unsubscribe from the subscription.
Unsubscribing Manually RxJS provides us with a convenient method to do this. It lives on the Subscription object and is simply called . unsubscribe() .
A more RxJS-ish way of doing what you want is to make use of the take
operator, like this:
this.puzzleService.login(this.nameoremail, this.password).pipe(
take(1)
).subscribe(success => {
// ...
});
This will make the observable emit exactly one value and then complete it.
However, @Picci is totally right that if your login
method returns a result from a HttpClient
request, you don't need to unsubscribe manually (nor use take
, for that matter).
Unsubscribing is important to avoid memory leaks, but it maybe not so important if you are "just wanting the ONE response from backend".
What I mean is that if, behind your this.puzzleService.login
you are using the Angular http
service, than you do not have to worry about unsubscribing since the service itself unsubscribes as soon as it gets the response from the backend, or an error occurs.
Unsubcribing is important when you face Observable streams which emit, by their nature, more than one value, and this is not the case of an http call but may be the case of web-sockets streams or other kind of streams.
This article from Ben Lesh, top contributor if not lead of RxJS, casts some light on the topic.
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