Memory leaks from unfinished subscriptions are a serious problem - like a ninja who forgot to return from a mission!
1import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
2import { DestroyRef, inject } from '@angular/core';
3
4@Component({...})
5export class ModernComponent {
6 private destroyRef = inject(DestroyRef);
7
8 constructor() {
9 // Automatically completes when the component is destroyed
10 this.dataService.getData().pipe(
11 takeUntilDestroyed()
12 ).subscribe(data => {
13 this.processData(data);
14 });
15
16 // Can also be used outside the constructor
17 this.loadData();
18 }
19
20 loadData(): void {
21 this.http.get('/api/data').pipe(
22 takeUntilDestroyed(this.destroyRef)
23 ).subscribe();
24 }
25}1import { Subject } from 'rxjs';
2import { takeUntil } from 'rxjs/operators';
3
4@Component({...})
5export class TraditionalComponent implements OnDestroy {
6 private destroy$ = new Subject<void>();
7
8 ngOnInit(): void {
9 this.dataService.getData().pipe(
10 takeUntil(this.destroy$)
11 ).subscribe(data => {
12 this.processData(data);
13 });
14
15 // Multiple subscriptions
16 this.otherService.getOther().pipe(
17 takeUntil(this.destroy$)
18 ).subscribe();
19 }
20
21 ngOnDestroy(): void {
22 this.destroy$.next();
23 this.destroy$.complete();
24 }
25}1@Component({
2 template: \`
3 @if (samuraiList$ | async; as samuraiList) {
4 @for (s of samuraiList; track s.id) {
5 <div>{{ s.name }}</div>
6 }
7 } @else {
8 <p>Loading...</p>
9 }
10 \`
11})
12export class SamuraiListComponent {
13 // AsyncPipe automatically subscribes and unsubscribes!
14 samuraiList$ = this.http.get<Samurai[]>('/api/samurai');
15}1import { Subscription } from 'rxjs';
2
3@Component({...})
4export class CollectionComponent implements OnDestroy {
5 private subscriptions = new Subscription();
6
7 ngOnInit(): void {
8 // Add subscriptions to the collection
9 this.subscriptions.add(
10 this.service1.data$.subscribe()
11 );
12
13 this.subscriptions.add(
14 this.service2.data$.subscribe()
15 );
16 }
17
18 ngOnDestroy(): void {
19 // One line cancels all
20 this.subscriptions.unsubscribe();
21 }
22}