RxJS in Angular

Observables Are Everywhere — But Less So Now

RxJS in Angular

HTTP, router events, form valueChanges — all Observables. Signals reduce the need for RxJS but streams remain essential.

5 min read Level 3/5 #angular#rxjs
What you'll learn
  • Subscribe and unsubscribe correctly
  • Use takeUntilDestroyed for safety
  • Apply common operators (map, filter, switchMap, debounceTime)

RxJS is the backbone of Angular’s async story. Even with signals taking over local state, you will still hit Observables every time you talk to HTTP, listen to router events, or watch form changes.

Subscribe without leaks

Every manual .subscribe() is a potential memory leak. The modern fix is takeUntilDestroyed, which ties the subscription to the component’s lifecycle.

import { Component, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs';

@Component({ selector: 'app-shell', standalone: true, template: '' })
export class ShellComponent {
  private router = inject(Router);

  constructor() {
    this.router.events
      .pipe(filter(e => e instanceof NavigationEnd), takeUntilDestroyed())
      .subscribe(e => console.log('navigated to', e));
  }
}

Operators you will use daily

  • map — transform each emitted value
  • filter — drop emissions that fail a predicate
  • switchMap — cancel the previous inner Observable when a new value arrives
  • debounceTime — wait for a pause in emissions
  • combineLatest — merge the latest value from multiple streams
import { FormControl } from '@angular/forms';
import { debounceTime, switchMap } from 'rxjs';

query = new FormControl('');

results$ = this.query.valueChanges.pipe(
  debounceTime(250),
  switchMap(q => this.http.get<User[]>(`/api/search?q=${q}`)),
);

switchMap is the secret sauce — without it, slow responses could overwrite fast ones and produce stale results.

Prefer signals when you can

For local component state, signal() is simpler and integrates with change detection natively. Reach for RxJS when you need streams over time: HTTP, events, websockets, debouncing.

The Async Pipe →