DEV Community

Cover image for Evitando problemas com Observables.
Carlos Moreira
Carlos Moreira

Posted on

Evitando problemas com Observables.

O Reactive Extensions Library for JavaScript (RxJS) é uma biblioteca muito poderosa, isso é inegável. Não foi à toa que a equipe do Angular a integrou em seu framework. Mas com grandes poderes vem grandes responsabilidades dentre estas estão os Observables.

Por que devo me preocupar com isso?

Fazendo uma analogia imagine que você se inscreveu em vários canais do youtube, mas alguns desses canais já não são mais do seu interesse. Enquanto você não anular a inscrição (unsubscribe), vai continuar recebendo as notificações desses canais.

Com Observable não é diferente. Ao chamar o método subscribe(), sua aplicação irá observar os eventos emitidos até que você diga que não tem mais interesse.

No exemplo abaixo usamos o operador interval que define um intervalo de tempo (passado como parâmetro) no qual o Observable irá emitir um evento.

Note que também vamos imprimir no console quando o componente for destruído, usando o lifecycle hook ngOnDestroy.

código do componente alpha

Nossa aplicação de exemplo tem duas páginas, onde é exibido o componente Alpha em uma e o Beta em outra.

Exemplo de problema com subscrições de Observables

Mesmo depois do componente Alpha ter sido destruído, os eventos do nosso Observable continuaram a chegar :(

Isso pode gerar comportamentos inesperados, problemas de performance, problemas de gerenciamento de memória etc.

Cuidando dos Observables

Devemos anular a inscrição de nossos Observables e podemos fazer isso das seguintes maneiras:

1. Usando o unsubscribe()

Quando nos inscrevemos em um Observable nos é retornado um objeto Subscription, que por sua vez, representa um recurso descartável. Podemos guardar a referência desse objeto para chamar o unsubscribe() no momento oportuno, como no lifecycle hook ngOnDestroy por exemplo.

Unsubscribe usando a referência do Subscription

Caso tenha mais de um Observable, podemos criar um array e guardar a referência das subscrições e assim como no exemplo anterior, no lifecycle hook ngOnDestroy chamar o unsubscribe(), porém dessa vez num laço forEach.

Unsubscribe usando a referência de vários Subscription

2. Usando takeUntil

Podemos também abusar mais do poder do RxJS e utilizar seus operadores para anular as inscrições, usando por exemplo o operador takeUntil.

Unsubscribe usando operador takeUntil

Atenção ao usar essa técnica, pois caso tenha outro operador após o takeUntil, como por exemplo operadores de transformação ou composição, pode ocorrer um subscription leak e não funcionar como esperado. Nicholas Jamieson explica esse problema com mais detalhes.
A dica é deixar esse operador por último sempre que possível.

3. Usando o AsyncPipe

Também podemos deixar na conta do Angular, fazendo com que ele se encarregue da anulação da inscrição.

Para isso, não faremos a inscrição diretamente no Observable. Passaremos essa tarefa para o nosso template usando as diretivas *ngFor ou *ngIf em conjunto com o AsyncPipe

componente alpha

Note que não chamamos o subscribe() dessa vez.

No template, atenção ao *ngIf="someDataAsObservable$ | async as i; else loading", ao usar o | async pedimos para o Angular se inscrever nesse Observable e entregar o resultado para a variável i assim que disponível.
Enquanto o valor não estiver disponível o if será avaliado como false e será exibido o conteúdo do nosso ng-template, conforme indicado no else.

componente alpha template

Vamos ver como ficou:

Unsubscribe com diretiva

Note que ao navegar para a página do componente Beta, paramos de ouvir os eventos do nosso Observable sem precisar chamar manualmente o unsubscribe().

E as chamadas http pelo HttpClient, também devo me preocupar ?

Essas estão na conta do Angular. Podemos confirmar no código fonte, a partir da linha 208, que após a resposta do servidor é chamado o complete() do Observable que pelo seu contrato, indica que já não vai mais emitir evento nenhum.
Então, menos uma preocupação pra gente :)

Resumindo

Essas são algumas maneiras de anular a inscrição de um Observable, ajudando a manter a aplicação saudável, sem uso desnecessário dos recursos do seu cliente e evitando problemas a medida que a aplicação cresce.

Não deixe seus Observables espalhados por aí ou eles podem te assombrar depois.

Isso é tudo pessoal

Top comments (0)