When you use Observables in Angular, it’s important to make sure that you unsubscribe from them properly to avoid memory leaks. Here are some best practices for unsubscribing from subscriptions:
- Use the
takeUntil
operator:
The takeUntil
operator is a common technique for unsubscribing from an Observable. You can create a subject that emits a value when the component is destroyed, and then use takeUntil
to automatically unsubscribe from the Observable when that value is emitted:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { UserService } from './user.service';
@Component({
selector: 'app-users-list',
template: `
<ul>
<li *ngFor="let user of users">{{ user.name }}</li>
</ul>
`
})
export class UsersListComponent implements OnInit, OnDestroy {
private unsubscribe$: Subject<void> = new Subject<void>();
users: User[];
constructor(private userService: UserService) { }
ngOnInit() {
this.userService.getUsers()
.pipe(takeUntil(this.unsubscribe$))
.subscribe((users: User[]) => {
this.users = users;
});
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
}
- Use the
async
pipe:
If you’re using Observables in your template, you can use the async
pipe to automatically subscribe and unsubscribe from the Observable:
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { UserService } from './user.service';
@Component({
selector: 'app-users-list',
template: `
<ul>
<li *ngFor="let user of users$ | async">{{ user.name }}</li>
</ul>
`
})
export class UsersListComponent {
users$: Observable<User[]>;
constructor(private userService: UserService) {
this.users$ = this.userService.getUsers();
}
}
- Use the
ngOnDestroy
lifecycle hook:
You can manually unsubscribe from Observables in the ngOnDestroy
lifecycle hook:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { UserService } from './user.service';
@Component({
selector: 'app-users-list',
template: `
<ul>
<li *ngFor="let user of users">{{ user.name }}</li>
</ul>
`
})
export class UsersListComponent implements OnInit, OnDestroy {
private subscription: Subscription;
users: User[];
constructor(private userService: UserService) { }
ngOnInit() {
this.subscription = this.userService.getUsers()
.subscribe((users: User[]) => {
this.users = users;
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
- Use the
ngOnDestroy
lifecycle hook and an array to store subscriptions:
You can also store all of your subscriptions in an array and unsubscribe from them in the ngOnDestroy
lifecycle hook:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { UserService } from './user.service';
@Component({
selector: 'app-users-list',
template: `
<ul>
<li *ngFor="let user of users">{{ user.name }}</li>
</ul>
`
})
export class UsersListComponent implements OnInit, OnDestroy {
private subscriptions: Subscription[] = [];
users: User[];
constructor(private userService: UserService) { }
ngOnInit() {
this.subscriptions.push(this.userService.getUsers()
.subscribe((users: User[]) => {
this.users = users;
}));
}
ngOnDestroy() {
this.subscriptions.forEach((subscription: Subscription) => {
subscription.unsubscribe();
});
}
}
In this example, we’re creating an array to store all of our subscriptions. In the ngOnInit
method, we’re pushing a new subscription onto the array when we subscribe to the UserService
‘s getUsers()
method. Then, in the ngOnDestroy
method, we’re iterating through the array and calling the unsubscribe()
method on each subscription.
By using this technique, we can easily manage all of our subscriptions and make sure they’re properly unsubscribed when the component is destroyed.
We hope this article helped you to find Best practices for unsubscribing from subscriptions.