There are several ways to unsubscribe from observables on Angular components (by using ngOnDestroy). Which option below should be preferred and why (e.g. technical reasons, performance, etc.)?
Using RxJS takeUntil to unsubscribe
@Component({
selector: "app-flights",
templateUrl: "./flights.component.html"
})
export class FlightsComponent implements OnDestroy, OnInit {
private readonly destroy$ = new Subject();
public flights: FlightModel[];
constructor(private readonly flightService: FlightService) {}
ngOnInit() {
this.flightService
.getAll()
.pipe(takeUntil(this.destroy$))
.subscribe(flights => (this.flights = flights));
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}
Explict call .unsubscribe(), e.g. by using a separate subscription instance
@Component({
selector: "app-flights",
templateUrl: "./flights.component.html"
})
export class FlightsComponent implements OnDestroy, OnInit {
private readonly subscriptions = new Subscription();
public flights: FlightModel[];
constructor(private readonly flightService: FlightService) {}
ngOnInit() {
const subscription = this.flightService
.getAll()
.subscribe(flights => (this.flights = flights));
this.subscriptions.add(subscription);
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
}
Using RxJS takeWhile unsubscribe
There is also a better way to unsubscribe from or complete Observables by using the takeUntil() operator. The takeUntil() operator emits the values emitted by the source Observable until a notifier Observable emits a value.
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…
As hand washing and social distancing is the major tool for elimination Corona Virus leak, as unsubscribing is the essential tool for avoiding memory leaks when we use Observables. It's the must thing to do, otherwise, we have unused object references inside our application.
TLDR; there is no wrong here. Choose what you see fits your needs and communicates your intent.
Ben Lesh has also written quite a good post about the different ways to unsubscribe https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87
His opinion:
You should probably be using operators like
takeUntil
to manage your RxJS subscriptions. As a rule of thumb, if you see two or more subscriptions being managed in a single component, you should wonder if you could be composing those better.
Personally, I choose option 1 as well, which is to use takeUntil
.
However, it is important for you to place the takeUntil()
operator on the last RxJS operator on the pipe sequence, as explained here.
For instance, if we do not place takeUntil()
as the last operator, the subscriber will remain subscribed to the subsequent switchMap()
operator:
this.flightService.getAll()
.pipe(
takeUntil(this.destroy$),
switchMap(() => this.doSomethingElse()),
).subscribe(flights => (this.flights = flights));
Therefore, the right way of doing so would be this:
this.flightService.getAll()
.pipe(
switchMap(() => this.doSomethingElse()),
takeUntil(this.destroy$),
).subscribe(flights => (this.flights = flights));
Brian Love has written a really good article on the different ways (including unsubscribe()
, and the takeUntil()
operator) of unsubscribing to observables. I would recommend you to take a look at it as well.
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