Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Dúvida] Quando o componente for destruído, o subscribe não é destruído junto dele?

Quando o componente for destruído, o subscribe não é destruído junto dele? Além disso, é possível usar o unsubscribe em outros locais, sem ser no ngOnDestroy ou seria uma boa prática usar dentro desse hook?

2 respostas
solução!

Olá Viviane, tudo bem?

Como mencionado no curso, quando um componente é destruído no Angular, o subscribe em um Observable não é automaticamente cancelado. Se você não cancelar explicitamente a assinatura, pode ocorrer um vazamento de memória, pois o Observable pode continuar emitindo valores e o componente pode tentar processá-los mesmo depois de ser destruído. Para gerenciar isso, a melhor opção é usar o unsubscribe no ngOnDestroy, assim como mencionado na aula, para cancelar as assinaturas manualmente. Mas, pesquisando, encontrei outras 2 formas de fazer isso e compartilho aqui com você:

1. Usando ngOnDestroy com Subscription

Você pode armazenar a assinatura em uma variável e cancelá-la no método ngOnDestroy assim como mencionado no curso:

import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { SomeService } from './some.service';

@Component({
  selector: 'app-some-component',
  templateUrl: './some-component.component.html',
  styleUrls: ['./some-component.component.css']
})
export class SomeComponent implements OnDestroy {
  private subscription: Subscription = new Subscription();

  constructor(private someService: SomeService) {
    this.subscription.add(this.someService.getData().subscribe(data => {
      // handle data
    }));
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe(); // Cancel all subscriptions
  }
}

2. Usando o takeUntil

Uma abordagem mais avançada e recomendada é usar o operador takeUntil junto com um Subject que emite um valor quando o componente é destruído. Isso garante que todas as assinaturas sejam canceladas quando o componente for destruído:

import { Component, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { SomeService } from './some.service';

@Component({
  selector: 'app-some-component',
  templateUrl: './some-component.component.html',
  styleUrls: ['./some-component.component.css']
})
export class SomeComponent implements OnDestroy {
  private destroy$ = new Subject<void>();

  constructor(private someService: SomeService) {
    this.someService.getData()
      .pipe(takeUntil(this.destroy$))
      .subscribe(data => {
        // handle data
      });
  }

  ngOnDestroy(): void {
    this.destroy$.next(); // Emite um valor para notificar os Observables
    this.destroy$.complete(); // Completa o Subject para liberar recursos
  }
}

3. Usando o async pipe

Se você estiver usando o Angular Template Syntax, o async pipe é uma forma prática de gerenciar assinaturas automaticamente:

No código HTML:

<!-- some-component.component.html -->
<div *ngIf="data$ | async as data">
  {{ data }}
</div>

No código TypeScript:

import { Component } from '@angular/core';
import { SomeService } from './some.service';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-some-component',
  templateUrl: './some-component.component.html',
  styleUrls: ['./some-component.component.css']
})
export class SomeComponent {
  data$: Observable<any>;

  constructor(private someService: SomeService) {
    this.data$ = this.someService.getData();
  }
}

O async pipe cancela automaticamente a assinatura quando o componente é destruído. Para aplicações maiores e mais complexas, o uso de takeUntil com um Subject é geralmente a solução mais robusta.

Espero ter ajudado! Bons estudos!

Natália

Ajudou muito! Muito obrigada pela resposta Natália!