<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Carlos Moreira</title>
    <description>The latest articles on DEV Community by Carlos Moreira (@carl0smore1ra).</description>
    <link>https://dev.to/carl0smore1ra</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F170707%2F2f0c5106-0602-41bf-a442-78dae9e71dc6.jpg</url>
      <title>DEV Community: Carlos Moreira</title>
      <link>https://dev.to/carl0smore1ra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/carl0smore1ra"/>
    <language>en</language>
    <item>
      <title>Evitando problemas com Observables.</title>
      <dc:creator>Carlos Moreira</dc:creator>
      <pubDate>Sun, 27 Oct 2019 23:59:57 +0000</pubDate>
      <link>https://dev.to/carl0smore1ra/evitando-problemas-com-observables-3j7b</link>
      <guid>https://dev.to/carl0smore1ra/evitando-problemas-com-observables-3j7b</guid>
      <description>&lt;p&gt;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 &lt;em&gt;&lt;strong&gt;Observables&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que devo me preocupar com isso?
&lt;/h2&gt;

&lt;p&gt;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 (&lt;code&gt;unsubscribe&lt;/code&gt;), vai continuar recebendo as notificações desses canais.&lt;/p&gt;

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

&lt;p&gt;No exemplo abaixo usamos o operador &lt;code&gt;interval&lt;/code&gt; que define um intervalo de tempo (passado como parâmetro) no qual o &lt;em&gt;Observable&lt;/em&gt; irá emitir um evento.&lt;/p&gt;

&lt;p&gt;Note que também vamos imprimir no console quando o componente for destruído, usando o &lt;em&gt;lifecycle hook&lt;/em&gt; &lt;code&gt;ngOnDestroy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Cv4rASP2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/pfy0piy9a0lnesntehoi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Cv4rASP2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/pfy0piy9a0lnesntehoi.png" alt="código do componente alpha"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wFEtqDVF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/40jo0k7yu674cm0m6b6m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wFEtqDVF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/40jo0k7yu674cm0m6b6m.gif" alt="Exemplo de problema com subscrições de Observables"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mesmo depois do componente Alpha ter sido destruído, os eventos do nosso &lt;em&gt;Observable&lt;/em&gt; continuaram a chegar :(&lt;/p&gt;

&lt;p&gt;Isso pode gerar comportamentos inesperados, problemas de performance, problemas de gerenciamento de memória etc. &lt;/p&gt;

&lt;h2&gt;
  
  
  Cuidando dos Observables
&lt;/h2&gt;

&lt;p&gt;Devemos anular a inscrição de nossos &lt;em&gt;Observables&lt;/em&gt; e podemos fazer isso das seguintes maneiras:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Usando o &lt;code&gt;unsubscribe()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Quando nos inscrevemos em um &lt;em&gt;Observable&lt;/em&gt; nos é retornado um objeto &lt;a href="https://rxjs-dev.firebaseapp.com/guide/subscription"&gt;Subscription&lt;/a&gt;, que por sua vez, representa um recurso descartável. Podemos guardar a referência desse objeto para chamar o &lt;code&gt;unsubscribe()&lt;/code&gt; no momento oportuno, como no &lt;em&gt;lifecycle hook&lt;/em&gt; &lt;code&gt;ngOnDestroy&lt;/code&gt; por exemplo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ILl7UB_q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jt7etn9jfu6843e1ivxr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ILl7UB_q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jt7etn9jfu6843e1ivxr.png" alt="Unsubscribe usando a referência do Subscription"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uIb4s_lu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jkvmlwchh3cvp8damqxs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uIb4s_lu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jkvmlwchh3cvp8damqxs.png" alt="Unsubscribe usando a referência de vários Subscription"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Usando &lt;code&gt;takeUntil&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Podemos também abusar mais do poder do RxJS e utilizar seus operadores para anular as inscrições, usando por exemplo o operador &lt;a href="https://rxjs-dev.firebaseapp.com/api/operators/takeUntil"&gt;&lt;code&gt;takeUntil&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lQYSAAL8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/db2xychfjrttdkzv3lwn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lQYSAAL8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/db2xychfjrttdkzv3lwn.png" alt="Unsubscribe usando operador takeUntil"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Atenção ao usar essa técnica, pois caso tenha outro operador após o &lt;code&gt;takeUntil&lt;/code&gt;, como por exemplo operadores de transformação ou composição, pode ocorrer um &lt;em&gt;subscription leak&lt;/em&gt; e não funcionar como esperado. &lt;a href="https://blog.angularindepth.com/rxjs-avoiding-takeuntil-leaks-fb5182d047ef"&gt;Nicholas Jamieson&lt;/a&gt; explica esse problema com mais detalhes.&lt;br&gt;
A dica é deixar esse operador por último sempre que possível.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Usando o &lt;code&gt;AsyncPipe&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Também podemos deixar na conta do Angular, fazendo com que ele se encarregue da anulação da inscrição.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2bxL5jsD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c1d78ej83kcia06h558t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2bxL5jsD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c1d78ej83kcia06h558t.png" alt="componente alpha"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note que não chamamos o &lt;code&gt;subscribe()&lt;/code&gt; dessa vez.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Dc8gJR_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/38kqw0djh5zqr9j1df8i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Dc8gJR_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/38kqw0djh5zqr9j1df8i.png" alt="componente alpha template"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos ver como ficou:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CUvZhF7I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hbo58pnwmkd60lmzu3qn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CUvZhF7I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hbo58pnwmkd60lmzu3qn.gif" alt="Unsubscribe com diretiva"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  E as chamadas http pelo &lt;code&gt;HttpClient&lt;/code&gt;, também devo me preocupar ?
&lt;/h3&gt;

&lt;p&gt;Essas estão na conta do Angular. Podemos confirmar &lt;a href="https://github.com/angular/angular/blob/master/packages/common/http/src/xhr.ts"&gt;no código fonte&lt;/a&gt;, a partir da &lt;strong&gt;linha 208&lt;/strong&gt;, que após a resposta do servidor é chamado o &lt;code&gt;complete()&lt;/code&gt; do &lt;em&gt;Observable&lt;/em&gt; que pelo seu &lt;a href="http://reactivex.io/documentation/contract.html"&gt;contrato&lt;/a&gt;, indica que já não vai mais emitir evento nenhum.&lt;br&gt;
Então, menos uma preocupação pra gente :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Resumindo
&lt;/h3&gt;

&lt;p&gt;Essas são algumas maneiras de anular a inscrição de um &lt;em&gt;Observable&lt;/em&gt;, 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.&lt;/p&gt;

&lt;p&gt;Não deixe seus &lt;em&gt;Observables&lt;/em&gt; espalhados por aí ou eles podem te assombrar depois.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ba0LTQCn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/e/ea/Thats_all_folks.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ba0LTQCn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/e/ea/Thats_all_folks.svg" alt="Isso é tudo pessoal"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>webperf</category>
    </item>
  </channel>
</rss>
