DEV Community

Habibur Rahman
Habibur Rahman

Posted on

Visualizing RxJS: The Ultimate Guide to `switchMap`, `mergeMap`, `concatMap`, and `exhaustMap`

If you are an Angular developer, you have likely encountered the "Nested Subscribe" anti-pattern.

// ❌ The Junior Anti-Pattern
this.route.params.subscribe(params => {
  // Nested subscription! Memory leaks and race conditions ahead.
  this.userService.getUser(params.id).subscribe(user => {
    this.user = user;
  });
});
Enter fullscreen mode Exit fullscreen mode

To fix this, we use Higher-Order Mapping Operators. These operators take an Observable, subscribe to it, and "flatten" the result into a single stream.

But RxJS gives us four of them. And choosing the wrong one can cause bugs that are incredibly hard to reproduce (like race conditions or out-of-order saves).

Let's break them down with real-world analogies.


1. mergeMap (The Parallel Map)

The Analogy: A busy highway entrance.
Cars (data) enter the highway whenever they want. They all drive alongside each other. It doesn't matter who finishes first; everyone runs at the same time.

How it works:

  • It subscribes to EVERY inner Observable immediately.
  • It handles multiple requests in parallel.
  • Order is NOT guaranteed (a small request might finish before a large one).

When to use it:

  • "Fire and Forget" actions.
  • Example: You have a list of items, and the user selects 5 and clicks "Delete". You want all 5 delete requests to run at the same time.
// ✅ Use mergeMap for parallel deletions
idsToDelete$.pipe(
  mergeMap(id => this.api.deleteItem(id))
).subscribe();
Enter fullscreen mode Exit fullscreen mode

2. switchMap (The Cancelling Map)

The Analogy: A TV Remote.
You press Channel 5. Before it loads, you press Channel 7. The TV immediately stops trying to load Channel 5 and switches to Channel 7.

How it works:

  • Only one inner subscription is active at a time.
  • If a new value arrives, it cancels (unsubscribes from) the previous one.

When to use it:

  • Read operations / Get requests.
  • Example: Search Typeahead. If the user types "Hello", we search. If they immediately type "Hello World", we don't care about the results for "Hello" anymore. Cancel it to save bandwidth.
// ✅ Use switchMap for search or route params
searchTerm$.pipe(
  switchMap(term => this.api.search(term))
).subscribe(results => this.results = results);
Enter fullscreen mode Exit fullscreen mode

3. concatMap (The Queue Map)

The Analogy: A Cafeteria Line.
You cannot buy your food until the person in front of you has paid. You must wait your turn.

How it works:

  • It queues up requests.
  • It waits for the current inner Observable to complete before starting the next one.
  • Order is guaranteed.

When to use it:

  • Write operations where order matters.
  • Example: Auto-Save. If I type "A", then "B", then "C", the API must receive them in that order. If "C" arrives before "B", the database is corrupted.
// ✅ Use concatMap for ordered saves
saveUpdates$.pipe(
  concatMap(update => this.api.save(update))
).subscribe();
Enter fullscreen mode Exit fullscreen mode

4. exhaustMap (The Ignoring Map)

The Analogy: A Do Not Disturb sign.
I am working. If you knock on my door, I will ignore you completely until I am finished.

How it works:

  • If an inner subscription is running, it ignores any new values from the source.
  • Once the inner subscription completes, it is ready to accept new values again.

When to use it:

  • Non-idempotent actions (Preventing Spam).
  • Example: Login Button. If the user frantically clicks "Login" 10 times, you only want to send ONE request. Ignore the other 9 clicks while the first one is processing.
// ✅ Use exhaustMap for submit buttons
submitClick$.pipe(
  exhaustMap(() => this.authService.login(this.form.value))
).subscribe();
Enter fullscreen mode Exit fullscreen mode

Summary Cheat Sheet

Operator Behavior Best For...
mergeMap Parallel, no cancelling Deletes, unrelated data fetching
switchMap Cancels old requests Search, Filters, Route Parameters
concatMap Waits in line (Queue) Updates, Saves, Ordered operations
exhaustMap Ignores while busy Login, Refresh Token, Submit Buttons

Stop guessing. Choose the operator that fits your data flow.

Top comments (0)