Introdução
Nos meus 6 anos trabalhando com Angular, uma pergunta recorrente que vejo aparecer, mesmo de devs com menos experiência, é: "Eu preciso me desinscrever aqui?"
A resposta é: sim, na maioria dos casos. Mas nem sempre é tão simples assim. Neste artigo, quero entender quando e como usar as desinscrições no Angular.
O que é desinscrição e por que é importante?
Em resumo, desinscrever-se de um observable significa parar de receber notificações dele. Isso é crucial para evitar vazamentos de memória e garantir que seu aplicativo Angular funcione de forma eficiente.
Imagine que você se inscreve para receber uma revista semanal com ofertas de um supermercado local. Essa revista é muito útil enquanto você mora perto do mercado, pois te mantém atualizado com as melhores promoções. Porém, se você se muda para outra cidade onde esse mercado não existe, continuar recebendo essa revista se torna desnecessário e só lota sua caixa de correio com conteúdo que você não vai usar. Nesse caso, é melhor cancelar a inscrição para evitar receber informações irrelevantes.
No Angular, os observables funcionam de maneira semelhante. Quando você se inscreve em um observable, você está basicamente pedindo para receber notificações sempre que algo novo acontecer. Se você não precisa mais dessas notificações, é importante se desinscrever para evitar que o observable continue enviando notificações desnecessárias, o que pode levar a vazamentos de memória.
Quando me desinscrever?
- Sempre que você não precisar mais das notificações do observable. Por exemplo, se você está buscando dados para uma tela e, em seguida, navega para outra tela, não precisa mais das notificações do observable da tela anterior.
-
Quando o componente que está criando a inscrição for destruído. Isso geralmente acontece automaticamente quando você navega para outra tela, mas é importante verificar se há casos em que isso não acontece e, se necessário, desinscrever-se manualmente no
ngOnDestroy
do componente.
Como me desinscrever?
Existem diversas maneiras de se desinscrever de um observable no Angular. Aqui estão alguns dos métodos mais comuns:
1. Usando o método unsubscribe()
Esse é o método mais básico e direto. Você pode armazenar a referência à inscrição em uma variável e chamá-la quando não precisar mais das notificações.
const subscription = myObservable.subscribe(data => {
console.log(data);
});
// ... algum tempo depois ...
subscription.unsubscribe();
2. Usando o operador takeUntil()
Esse operador permite que você se desinscreva de um observable quando outro observable for concluído. Isso é útil em situações em que você deseja se desinscrever de um observable principal quando um observable secundário for concluído.
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
const subject = new Subject();
const subscription = myObservable.pipe(
takeUntil(subject)
).subscribe(data => {
console.log(data);
});
// ... algum tempo depois ...
subject.next();
3. Usando bibliotecas de terceiros
Existem diversas bibliotecas de terceiros que podem te ajudar a gerenciar desinscrições de forma mais fácil. Uma biblioteca popular é o ngx-unsubscribe
.
Desinscrição automática com bibliotecas nativas do Angular
Algumas bibliotecas nativas do Angular já fazem a desinscrição automaticamente. É o caso do HttpClientModule
e do Router
. Isso significa que você não precisa se preocupar em se desinscrever das solicitações HTTP ou das alterações de rota.
HttpClientModule
O HttpClientModule
desinscreve automaticamente das solicitações HTTP quando a requisição é concluída ou quando o componente que fez a requisição é destruído.
Router
O Router
desinscreve automaticamente das alterações de rota quando a navegação é concluída ou quando o componente que está escutando as alterações de rota é destruído.
O async Pipe
O async
pipe é uma maneira conveniente de lidar com observables no template do Angular. Ele automaticamente se inscreve no observable e se desinscreve quando o componente é destruído. Isso ajuda a evitar vazamentos de memória sem precisar escrever código de desinscrição manual.
Exemplo de uso do async
pipe:
<div *ngIf="authService.isLoggedIn$ | async as isLoggedIn">
<p *ngIf="isLoggedIn">Você está logado!</p>
<p *ngIf="!isLoggedIn">Você não está logado.</p>
</div>
Neste exemplo, isLoggedIn$
é um observable exposto pelo serviço AuthService
. O async
pipe se inscreve nesse observable e atualiza automaticamente o template com base no seu valor atual.
E os observables do Reactive Forms?
No caso dos observables do Reactive Forms, a desinscrição geralmente não é necessária. Isso porque esses observables são gerenciados internamente pelo Angular e são desinscritos automaticamente quando o componente é destruído.
Exemplo Prático: Usando valueChanges
e Desinscrição em um Componente de Login
Vamos ver um exemplo prático de como usar a desinscrição em um componente de login simples. No nosso exemplo, vamos usar o operador takeUntil
para nos desinscrever quando o componente for destruído e também monitorar as mudanças de valor dos campos de entrada.
import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { AuthService } from '../auth.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Router } from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit, OnDestroy {
loginForm: FormGroup;
private unsubscribeSubject = new Subject<void>();
constructor(private authService: AuthService, private router: Router) { }
ngOnInit(): void {
this.loginForm = new FormGroup({
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [Validators.required])
});
// Monitorar mudanças de valor usando valueChanges
this.loginForm.valueChanges
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(changes => {
console.log('Form value changed:', changes);
});
}
ngOnDestroy(): void {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
onSubmit(): void {
const { email, password } = this.loginForm.value;
this.authService.login(email, password)
.pipe(
takeUntil(this.unsubscribeSubject) // Desinscreve quando o unsubscribeSubject for emitido
)
.subscribe(
() => {
// Login efetuado com sucesso
this.router.navigate(['/']);
},
(error) => {
// Erro no login
console.error(error);
}
);
}
}
Neste exemplo, além de usar o operador takeUntil
para desinscrever-se do observable de login quando o componente for destruído, também monitoramos as mudanças de valor do formulário usando valueChanges
. Isso garante que as mudanças de valor sejam registradas enquanto o componente está ativo e paradas quando o componente é destruído.
Resumo
Neste artigo, vimos que as desinscrições são cruciais para evitar vazamentos de memória e garantir que seu aplicativo Angular funcione de forma eficiente. Abordamos os seguintes tópicos:
- O que é desinscrição e por que é importante?
- Quando me desinscrever?
- Como me desinscrever?
- Desinscrição automática com bibliotecas nativas do Angular
- O
async
Pipe - E os observables do Reactive Forms?
- Exemplo prático: Usando
valueChanges
e Desinscrição em um Componente de Login
Espero que este artigo tenha te ajudado a entender melhor o conceito de desinscrições no Angular e como aplicá-lo em seus projetos.
Dicas Extras:
- Sempre que você criar uma inscrição em um observable, pense em como você vai se desinscrever dela.
- Utilize ferramentas como o Angular DevTools para inspecionar as inscrições em seus componentes e identificar possíveis vazamentos de memória.
- Adote bibliotecas de terceiros como o
ngx-unsubscribe
para facilitar o gerenciamento de desinscrições em seus projetos.
Lembre-se: desinscrever-se é uma prática essencial para o desenvolvimento de aplicativos Angular robustos e eficientes.
Top comments (0)