A forma mais simples de se desinscrever de um Observable no Angular
Se você possui um conhecimento básico de Angular com certeza já deve ter ouvido falar sobre o perigo de realizar um subscribe num Observable e esquecer de se desinscrever dele posteriormente.
E é fato. Caso isso ocorra você terá sérios problemas de memory leak na sua aplicação. Portanto sempre prefira utilizar um observable diretamente no template com o uso do pipe async
. O Angular irá se encarregar de se inscrever e desinscrever quando o componente for destruído.
Porém existem situações onde de fato precisamos realizar o subscribe diretamente no código. Então quase sempre é preciso se lembrar de fazer o unsubscribe. A forma mais comum é guardando a subscription numa váriavel e no ngOnDestroy chamar o unsubscribe por ela.
@Component({...})
export class AppComponent implements OnInit, OnDestroy {
subscription: Subscription ; ngOnInit () {
const observable$ = interval(1000);
this.subscription = observable$.subscribe(x => console.log(x));
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Outra forma bastante conhecida é a de utilizar um Subject que deverá avisar o Observable que ele deve ser encerrado por meio do operador takeUntil
.
@Component({...})
export class AppComponent implements OnInit, OnDestroy {
notifier$ = new Subject(); ngOnInit () {
const observable$ = interval(1000);
observable$.pipe(takeUntil(this.notifier$))
.subscribe(x => console.log(x));
} ngOnDestroy() {
this.notifier$.next();
this.notifier$.complete();
}
}
Existem outras maneiras, porém todas elas acabam sendo um pouco custosas, e se você tem diversos subscribes espalhados pela sua aplicação então acaba sendo uma tarefa um tanto maçante.
Uma Solução simples e elegante
A biblioteca ngneat/until-destroy do Netanel Basal propõe uma solução onde a implementação é mínima. Basta inserir o decorator @UntilDestroy
e no seu observable e encadear o operador untilDestroyed(this)
. Fazendo isso temos o mesmo comportamento das soluções anteriores, só que deixando o seu código mais “limpo”!
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
@UntilDestroy()
@Component({})
export class InboxComponent {
ngOnInit() {
interval(1000)
.pipe(untilDestroyed(this))
.subscribe();
}
}
Ela ainda traz algumas outras funcionalidades bastante interessantes como a possibilidade de se desinscrever em observables que estão dentro de serviços que não sejam “Singleton”. Vale a pena ler a documentação, pois existem algumas situações onde precisamos realizar o unsubscribe em outros momentos e a biblioteca também poderá atender as suas necessidades.
Atenção: Antes de utilizá-la verifique em qual versão do Angular que a sua aplicação está para poder utilizá-la de forma correta!