Chapter 9.4โ˜• 15 min read

RxJS Operators

Operators transform, filter, and combine Observables. They are pipes through which data flows โ€” map, filter, switchMap, debounceTime, and more.

01What are Operators

Operators are functions that transform, filter, or combine Observables. They are used inside the .pipe() method.

import { of } from 'rxjs';
import { map, filter } from 'rxjs/operators';

of(1, 2, 3, 4, 5).pipe(
  filter(n => n % 2 === 0), // Only even numbers
  map(n => n * 10)           // Multiply by 10
).subscribe(v => console.log(v));
// Output: 20, 40

"Operator = filter โ€” paani se ganda pani alag karo, clean pani niklo."

Key concept: Operators don't change the original Observable. They return a NEW Observable with the transformation applied. This is called immutability.

Chain as many operators as you want โ€” each one processes the output of the previous:

obs$.pipe(
  filter(x => x > 10),    // 1st: filter
  map(x => x * 2),        // 2nd: transform
  debounceTime(300),      // 3rd: debounce
  tap(x => console.log(x)) // 4th: side effect
);
02Transformation Operators

Transformation operators change the values emitted by the Observable.

import { map, pluck, mapTo } from 'rxjs/operators';

// map โ€” transform each value (MOST USED)
of(1, 2, 3).pipe(
  map(x => x * 10)
).subscribe(v => console.log(v)); // 10, 20, 30

// map with objects
of({ name: 'Chicken Biryani', price: 299 }, { name: 'Mutton Biryani', price: 399 }).pipe(
  map(biryani => `${biryani.name}: โ‚น${biryani.price}`)
).subscribe(v => console.log(v));
// "Chicken Biryani: โ‚น299", "Mutton Biryani: โ‚น399"

// pluck โ€” extract property (deprecated, use map instead)
of({ name: 'Biryani', price: 299 }).pipe(
  pluck('name') // Get just the 'name' property
).subscribe(v => console.log(v)); // 'Biryani'

// mapTo โ€” ignore value, emit constant (rarely used)
of(1, 2, 3).pipe(
  mapTo('Hello')
).subscribe(v => console.log(v)); // 'Hello', 'Hello', 'Hello'

"map = translator โ€” jo aata hai usko badal ke do."

map is the most commonly used operator. You'll use it constantly to transform API responses, format data for display, or extract specific properties.

03Filtering Operators

Filtering operators control WHICH values pass through the pipe.

import { filter, take, takeWhile, distinctUntilChanged, debounceTime } from 'rxjs/operators';
import { from, of } from 'rxjs';

// filter โ€” only pass values matching condition
from([5, 12, 3, 8, 15]).pipe(
  filter(x => x > 10)
).subscribe(v => console.log(v)); // 12, 15

// take(3) โ€” take first 3 values then auto-complete
from([10, 20, 30, 40, 50]).pipe(
  take(3)
).subscribe(v => console.log(v)); // 10, 20, 30 (then complete)

// distinctUntilChanged โ€” skip if same as previous
from([1, 1, 2, 2, 2, 3, 1]).pipe(
  distinctUntilChanged()
).subscribe(v => console.log(v)); // 1, 2, 3, 1 (consecutive duplicates removed)

// debounceTime(300) โ€” wait 300ms of silence before emitting
// THIS IS THE MOST USED FILTERING OPERATOR IN ANGULAR
searchInput$.pipe(
  debounceTime(300) // Wait for user to pause typing
).subscribe(searchTerm => {
  // Only fires after 300ms of no typing
});

"Filter = chhann โ€” sirf wanted values pass karo."

debounceTime is the most used filtering operator โ€” it's essential for search inputs, preventing API calls on every keystroke.

04Combination Operators

Combination operators work with Observables that return other Observables (higher-order Observables).

import { switchMap, mergeMap, concatMap } from 'rxjs/operators';
import { from, of } from 'rxjs';

// Imagine we have IDs and need to fetch details for each
const ids$ = of(1, 2, 3);
const fetchDetail = (id: number) => of({ id, name: `Item ${id}` });

// switchMap โ€” cancel previous, take LATEST (for search!)
ids$.pipe(
  switchMap(id => fetchDetail(id))
).subscribe(v => console.log(v));
// Only requests for latest ID complete โ€” previous ones cancelled

// mergeMap โ€” ALL at once (order may vary)
ids$.pipe(
  mergeMap(id => fetchDetail(id))
).subscribe(v => console.log(v));
// All three requests fire simultaneously, results in any order

// concatMap โ€” queue, one at a time (preserves order)
ids$.pipe(
  concatMap(id => fetchDetail(id))
).subscribe(v => console.log(v));
// 1 finishes โ†’ 2 starts โ†’ 2 finishes โ†’ 3 starts โ†’ 3 finishes

switchMap is the MOST USED combination operator in Angular.

Use switchMap for: search-as-you-type (cancel previous), auto-complete, tab switching, any "latest value matters" scenario.

// Real-world search pattern
this.searchInput.valueChanges.pipe(
  debounceTime(300),       // Wait for pause
  distinctUntilChanged(),  // Skip if same value
  switchMap(term =>        // Cancel previous search
    this.http.get(`/api/search?q=${term}`)
  )
).subscribe(results => this.results = results);
05Utility Operators

Utility operators do side effects, handle errors, or add helper behavior.

import { tap, catchError, retry, delay, startWith } from 'rxjs/operators';
import { of } from 'rxjs';

// tap โ€” do something without changing the value (debugging, logging)
of(1, 2, 3).pipe(
  tap(x => console.log('Before:', x)),
  map(x => x * 10),
  tap(x => console.log('After:', x))
).subscribe();
// Before: 1 โ†’ After: 10 โ†’ Before: 2 โ†’ After: 20 ...

// catchError โ€” catch errors, return fallback
this.http.get('/api/biryani').pipe(
  catchError(error => {
    console.error('API Error:', error);
    return of([]); // Return fallback โ€” app continues
  })
);

// retry(3) โ€” retry failed observable up to 3 times
this.http.get('/api/biryani').pipe(
  retry(3), // Try 3 times before giving up
  catchError(() => of([])) // If still fails, return fallback
);

// startWith('LOADING') โ€” emit initial value before source
this.http.get('/api/biryani').pipe(
  map(biryanis => ({ status: 'DONE', data: biryanis })),
  startWith({ status: 'LOADING', data: [] }) // Show loading immediately
);

"Utility = side kaam โ€” log karo, error handle karo, retry karo."

These operators make Angular apps robust: catchError prevents crashes, retry handles network glitches, startWith improves UX.

Key Takeaways

  • โœ… Operators are functions inside .pipe() โ€” immutable, return new Observable with transformation
  • โœ… map() โ€” transform values (MOST POPULAR), filter() โ€” pass/filter values, debounceTime(ms) โ€” wait for pause
  • โœ… switchMap โ€” cancel previous, take latest (for search, tabs); mergeMap โ€” all at once; concatMap โ€” queue
  • โœ… tap() โ€” side effects without changing value; catchError() โ€” handle errors, return fallback
  • โœ… retry(n) โ€” retry failed observable n times; startWith(initial) โ€” emit default before source
Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase