Munsif.
AboutExperienceProjectsAchievementsBlogsContact
HomeAboutExperienceProjectsAchievementsBlogsContact
Munsif.

Frontend Developer crafting scalable web applications with modern technologies and clean code practices.

Quick Links

  • About
  • Experience
  • Projects
  • Achievements

Connect

Ā© 2025 Shaik Munsif. All rights reserved.

Built with Next.js & Tailwind

Back to Blogs
RxJS

RxJS Mapping Operators Explained: map, switchMap, mergeMap, concatMap & exhaustMap

Finally understand RxJS mapping operators! Learn the difference between switchMap, mergeMap, concatMap, and exhaustMap using the Restaurant Analogy, decision trees, and real-world scenarios.

Dec 5, 202512 min read
RxJSOperatorsAngularReactive Programming

The Restaurant Analogy šŸ½ļø

Imagine you're a waiter at a restaurant. Customers (events) place orders (trigger inner Observables). How you handle multiple orders defines which operator you are!


Meet the Operators

map() - The Simple Transformer

What it does: Transforms each value. No inner Observables involved.

Analogy: šŸ­ A factory assembly line - each item gets the same transformation.

of(1, 2, 3).pipe(
  map(x => x * 10)
);
// Output: 10, 20, 30

switchMap() - The Impatient Waiter

What it does: Cancels previous inner Observable, switches to new one.

Analogy: šŸ½ļø "Forget my pasta order, I want pizza now!" - Only the latest order matters.

searchInput.valueChanges.pipe(
  switchMap(term => this.searchService.search(term))
);

āœ… Best for: Search autocomplete, route changes, polling


mergeMap() - The Multitasking Kitchen

What it does: Runs all inner Observables in parallel.

Analogy: šŸ½ļø "All orders to the kitchen!" - Everyone cooks at once.

from(files).pipe(
  mergeMap(file => this.upload(file), 3) // max 3 parallel
);

āœ… Best for: Bulk uploads, parallel API requests


concatMap() - The One-Chef Kitchen

What it does: Waits for each to complete before starting next.

Analogy: šŸ½ļø "One order at a time, in exact sequence."

from(transactions).pipe(
  concatMap(tx => this.bankService.process(tx))
);

āœ… Best for: Bank transactions, chat messages, sequential saves


exhaustMap() - The Focused Waiter

What it does: Ignores new emissions while current is running.

Analogy: šŸ½ļø "I'm busy with this order, come back later!"

loginButton.clicks.pipe(
  exhaustMap(() => this.authService.login())
);
// Rapid clicks are ignored!

āœ… Best for: Login buttons, form submits, refresh buttons


The Ultimate Decision Tree


Scenario Decision Tree


Quick Scenario Matcher

ScenarioOperatorWhy
šŸ” Search autocompleteswitchMapOnly latest matters
🧭 Route params changeswitchMapOnly current route
šŸ“¤ Upload multiple filesmergeMapParallel is faster
šŸ“Š Load dashboard widgetsmergeMapAll load at once
šŸ’¬ Send chat messagesconcatMapOrder preserved
šŸ’° Bank transactionsconcatMapSequence critical
šŸ” Login buttonexhaustMapPrevent double-login
šŸ›’ Add to cart clickexhaustMapPrevent duplicates

Comparison Cheat Sheet

OperatorConcurrencyCancels PrevKeeps OrderBest For
mapN/AN/AYesTransform
switchMap1āœ… YesLatest onlySearch
mergeMapUnlimitedāŒ NoāŒ NoParallel
concatMap1 (queue)āŒ Noāœ… YesSequential
exhaustMap1 (ignore)IgnoresFirst onlySpam prevention

Common Mistakes

āŒ Using mergeMap for search

// Wrong - race conditions!
searchInput.pipe(
  mergeMap(term => this.search(term))
);

// Right
searchInput.pipe(
  switchMap(term => this.search(term))
);

āŒ Using switchMap for saves

// Wrong - may cancel saves!
formChanges.pipe(
  switchMap(data => this.save(data))
);

// Right
formChanges.pipe(
  concatMap(data => this.save(data))
);

Summary: One-Line Definitions

  • map: Transform values (no Observables)
  • switchMap: Cancel old, use new (search)
  • mergeMap: Run all parallel (uploads)
  • concatMap: One at a time, in order (transactions)
  • exhaustMap: Ignore new while busy (submit buttons)

Written by

Shaik Munsif

Read more articles