Kurs Angular · Moduł 7: RxJS

Zarządzanie Subskrypcjami

2 min czytania ·
W tej lekcji4

Wycieki pamięci przez niezakończone subskrypcje to poważny problem - jak ninja, który zapomniał wrócić z misji!

takeUntilDestroyed (Angular 16+) - Zalecane

import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DestroyRef, inject } from '@angular/core';

@Component({...})
export class ModernComponent {
  private destroyRef = inject(DestroyRef);

  constructor() {
    // Automatycznie kończy przy zniszczeniu komponentu
    this.dataService.getData().pipe(
      takeUntilDestroyed()
    ).subscribe(data => {
      this.processData(data);
    });

    // Można też użyć poza konstruktorem
    this.loadData();
  }

  loadData(): void {
    this.http.get('/api/data').pipe(
      takeUntilDestroyed(this.destroyRef)
    ).subscribe();
  }
}

Tradycyjne podejście z Subject

import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

@Component({...})
export class TraditionalComponent implements OnDestroy {
  private destroy$ = new Subject<void>();

  ngOnInit(): void {
    this.dataService.getData().pipe(
      takeUntil(this.destroy$)
    ).subscribe(data => {
      this.processData(data);
    });

    // Wiele subskrypcji
    this.otherService.getOther().pipe(
      takeUntil(this.destroy$)
    ).subscribe();
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

AsyncPipe - Automatyczne Zarządzanie

@Component({
  template: `
    @if (samuraje$ | async; as samuraje) {
      @for (s of samuraje; track s.id) {
        <div>{{ s.name }}</div>
      }
    } @else {
      <p>Ładowanie...</p>
    }
  `
})
export class SamuraiListComponent {
  // AsyncPipe automatycznie subskrybuje i anuluje!
  samuraje$ = this.http.get<Samurai[]>('/api/samurai');
}

Subscription Collection

import { Subscription } from 'rxjs';

@Component({...})
export class CollectionComponent implements OnDestroy {
  private subscriptions = new Subscription();

  ngOnInit(): void {
    // Dodawaj subskrypcje do kolekcji
    this.subscriptions.add(
      this.service1.data$.subscribe()
    );

    this.subscriptions.add(
      this.service2.data$.subscribe()
    );
  }

  ngOnDestroy(): void {
    // Jedna linia anuluje wszystkie
    this.subscriptions.unsubscribe();
  }
}

Hasła z dokumentacji w tej lekcji

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Jaka jest zalecana metoda zarządzania subskrypcjami w Angular 16+?

  2. 2. Co AsyncPipe robi automatycznie?

To 2 z 3 pytań do tej lekcji. Pozostałe rozwiążesz w grze.

Zadania praktyczne w grze

  • Układanie w poziomie

    Ułóż import operatora takeUntilDestroyed z pakietu interop:

  • Edytor kodu

    Uzupełnij kod tak, by subskrypcja interval() kończyła się sama, gdy komponent zostanie zniszczony.

  • Układanie w pionie

    Ułóż kroki tradycyjnego wzorca sprzątania subskrypcji z Subject w kolejności występowania w komponencie:

  • Klikanie w kolejności

    Ułóż wyrażenie AsyncPipe z aliasem w szablonie: samuraje$ | async; as samuraje

Przydatne artykuły