Tratando vazamento de memória em aplicações Angular.

Alvaro Camillo Neto
TOTVS Developers
3 min readJun 4, 2019

--

Quando começamos o aprendizado de uma aplicação Angular, aprendemos o básico de RxJS para criar nossos componentes, principalmente quando temos que realizar alguma requisição HTTP. (link)

O conceito de Observable implementado no RxJS é poderoso e nos permite acessar um fluxo de dados (como uma requisição Http) de uma maneira fluída e organizada.

Nesse exemplo eu estou fazendo uma requisição na API e me inscrevendo (subscribe) no retorno para atribuir a um objeto que usarei na minha interface.

Porém, nesse simples exemplo mora um perigo não muito claro, a ameaça silenciosa do vazamento de memória.

Quando esse componente não for mais utilizado, como por exemplo se o usuário ir para outra página, o Observable gerado por essa requisição HTTP ainda estará ativo pois o componente não se desinscreveu nele.

Como o componente já foi destruído, esse Observable ainda ativo virou um vazamento de memória(memory leak).

Meme do buzz descrevendo “Memory leaks evereywhere.

Isso causa uma degradação do desempenho, aumento do consumo de recursos da máquina e principalmente, perda de tempo do desenvolvedor, pois em uma aplicação grande esse tipo de erro é bem complicado de se localizar.

Então, o que podemos fazer ? Simples: garantir que meu componente se desinscreva sempre que ele não precisar mais do Observable!

OK, mas como fazer isso? Ah! Para isso temos algumas maneiras…

A Básica.

Para se desinscrever de um Observable basta você seguir dois passos:

  • Guardar a inscrição: O método subscribe tem como retorno um objeto do tipo subscription que representa a inscrição realizada.
  • Chamar o método unsubscribe do objeto subscription.

Isso é simples, porém a questão é quando chamar o unsubscribe.

No Angular os componentes possuem métodos de ciclo de vida (Lifecycle Hooks), normalmente quando criamos via cli (ng g c) ele já vem de fábrica com o método OnInit.

Para desinscrever o componente do Observable antes dele ser destruído, podemos então utilizar o método OnDestroy.

Pronto vazamento eliminado!

Porém nem sempre nossos componentes terão apenas um Observable,assim essa solução simples pode ficar um pouco feia …

Veja que adicionamos mais um Observable e tivemos que guardar mais uma Subscription e realizar mais uma condição no método onDestroy.

Podemos melhorar?

O SubSink

Entra a biblioteca SubSink focada em facilitar a coleta e a desinscrição nos Observables.

Ela é muito simples e tem apenas um método e um atributo:

  • O atributo sink onde você adiciona a inscrição em uma lista que fica implícita.
  • O método unsubscribe que realiza a desinscrição de toda a lista do atributo sink.

Vamos ao exemplo anterior verificar como fica mais simples a administração dos Observables do componente.

Ainda temos mais uma alternativa. E essa já vem por padrão no Angular.

O pipe async.

Quando componentes utilizam Observables em seus templates HTML uma alternativa muito interessante é o pipe async ( | async).

Com ele o componente apenas passa para o template o observable. E o motor de renderização do Angular faz o trabalho de realizar a inscrição (subscribe) e atribuir o retorno a um objeto.

A melhor parte é que o Angular cuida da desinscrição para você!

Vamos ver como ficam o template e o componente:

Veja que não temos que chamar o OnDestroy, o framework faz isso para você!

Para mais informações, segue o vídeo da Loiane sobre o tema(vídeo).

Conclusão

Nesse artigo vimos os cuidados que temos que ter para evitar vazamento de memória (memory leaks) nas nossa aplicações Angular.

Resumindo:

  • Se seu componente utiliza observables para apresentar informações no template, utilize o pipe async.
  • Se você tem apenas um observable onde você precise fazer a inscrição(subscribe), guarde o objeto Subscription em uma variável e se desinscreva no método OnDestroy do componente.
  • Caso seu componente tenha vários observables, utilize a bibiloteca SubSink para seu código ficar mais limpo.

Código fonte do exemplo(link).

Obrigado e compartilhe esse artigo com seus colegas para eles conhecerem esses cuidados na construção de componentes Angular.

--

--