When working with Angular or JavaScript applications, handling asynchronous data streams effectively is critical. That’s where RxJS operators like switchMap, mergeMap, concatMap, and exhaustMap come into play.
In this blog, we’ll break down each operator in the simplest way possible—using dummy observable values so you can clearly see the difference. 🚀
🔄 What is RxJS?
RxJS (Reactive Extensions for JavaScript) is a library for reactive programming using observables. It makes it easier to handle asynchronous tasks such as HTTP requests, user input, timers, or WebSockets.
But since observables can emit multiple values, we often need to decide how to handle those emissions—and that’s where higher-order mapping operators like switchMap, mergeMap, concatMap, and exhaustMap come in.
📌 1. switchMap
👉 Definition: Cancels the previous observable and switches to the latest one.
👉 Use case: Search bar autocomplete (user typing fast).
import { of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
of('A', 'B', 'C').pipe(
switchMap(val => of(`${val} -> switched`))
).subscribe(res => console.log('switchMap:', res));
/**
Output:
switchMap: C -> switched
(Only the latest "C" is kept, "A" and "B" are canceled)
*/
âś… Key takeaway: Keeps only the most recent value.
⚡ 2. mergeMap
👉 Definition: Subscribes to all inner observables in parallel.
👉 Use case: Handling multiple API calls that can run at the same time.
import { of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
of('A', 'B', 'C').pipe(
mergeMap(val => of(`${val} -> merged`))
).subscribe(res => console.log('mergeMap:', res));
/**
Output:
mergeMap: A -> merged
mergeMap: B -> merged
mergeMap: C -> merged
(All run in parallel, order not guaranteed in async case)
*/
âś… Key takeaway: Processes everything simultaneously.
📚 3. concatMap
👉 Definition: Runs each inner observable sequentially, one after another.
👉 Use case: Form submissions or API requests that must be executed in order.
import { of } from 'rxjs';
import { concatMap } from 'rxjs/operators';
of('A', 'B', 'C').pipe(
concatMap(val => of(`${val} -> concatenated`))
).subscribe(res => console.log('concatMap:', res));
/**
Output:
concatMap: A -> concatenated
concatMap: B -> concatenated
concatMap: C -> concatenated
(Runs one by one, preserving order)
*/
âś… Key takeaway: Maintains strict order.
đźš« 4. exhaustMap
👉 Definition: Ignores new values while the current observable is still active.
👉 Use case: Login button click or form submission (prevents double requests).
import { of } from 'rxjs';
import { exhaustMap } from 'rxjs/operators';
of('A', 'B', 'C').pipe(
exhaustMap(val => of(`${val} -> exhausted`))
).subscribe(res => console.log('exhaustMap:', res));
/**
Output:
exhaustMap: A -> exhausted
("B" and "C" are ignored because "A" was still active)
*/
âś… Key takeaway: Only the first emission is considered until it finishes.
📊 Quick Comparison Table
🎯 Conclusion
Choosing the right operator depends on the use case:
Use switchMap for latest-only streams (like search).
Use mergeMap when all results are needed in parallel.
Use concatMap when order matters.
Use exhaustMap to ignore spamming actions like multiple clicks.
By understanding these four RxJS operators, you can write cleaner, more efficient Angular and Node.js code.
Top comments (0)