Angular developers frequently use RxJS operators, but many still stay confused about when to use switchMap, mergeMap, concatMap, or exhaustMap.
These operators look similar, but they behave very differently in real-world applications.
This guide explains them in simple Indian English, using easy diagrams, case studies, and rules you can apply immediately in production.
1. Why These Operators Matter
All four operators deal with higher-order Observables.
Meaning: an Observable that returns another Observable.
Example
search$.pipe(
switchMap(keyword => this.api.search(keyword))
)
The inner function returns a new request Observable.
The operator decides how Angular handles multiple emissions.
2. Visual Summary Table (Most Important)
| Operator | Cancels previous? | Order preserved? | Runs in parallel? | Best for |
|---|
| switchMap | Yes | No | No | Search boxes, type-ahead |
| mergeMap | No | No | Yes | Multiple parallel API calls |
| concatMap | No | Yes | No | Queue requests, one by one |
| exhaustMap | Yes (ignores new ones) | No | No | Forms, login button, prevent double submit |
Memorise this block. It explains 80 percent of practical cases.
3. switchMap — Most Common for Search and Live Updates
Behaviour
Use Case
Typing in a search box.
Example
this.searchControl.valueChanges.pipe(
debounceTime(300),
switchMap(text => this.api.search(text))
)
.subscribe(result => this.results = result);
Explanation
If the user types “ang", then “angu”, then “angular”,
switchMap cancels the earlier API calls.
Real-World Use Cases
4. mergeMap — Run Everything in Parallel
Behaviour
Does not cancel previous requests
Executes all inner Observables concurrently
Response order is not guaranteed
Example
from(ids).pipe(
mergeMap(id => this.api.getItem(id))
)
.subscribe(console.log);
Requests
Real-World Use Cases
Warning
Do not use mergeMap for user-typed searches.
It will spam your backend with unnecessary calls.
5. concatMap — Perfect When Order Matters
Behaviour
Example
from(ids).pipe(
concatMap(id => this.api.updateItem(id))
)
.subscribe(console.log);
Real-World Use Cases
Best Example
Updating 10 records in correct order:
items$.pipe(
concatMap(item => this.api.save(item))
)
Everything waits patiently.
Safe and predictable.
6. exhaustMap — Ignore New Requests While One Is Running
Behaviour
When a request starts, ignore all new emissions
After completion, accept the next one
Example
fromEvent(button, 'click').pipe(
exhaustMap(() => this.api.submitForm(form))
)
.subscribe();
Real-World Use Cases
Simple Understanding
exhaustMap = Work on one item and ignore everything else till done.
7. The Best Real-World Case Studies
Case Study 1: Search Text Box
Requirement: Only latest query matters
Solution: switchMap
search$.pipe(
debounceTime(300),
switchMap(query => this.api.search(query))
)
Case Study 2: Uploading Multiple Images
Requirement: All uploads should happen together
Solution: mergeMap
from(files).pipe(
mergeMap(file => this.api.upload(file))
)
Case Study 3: Save Each Step of a Wizard Form
Requirement: Save data in order
Solution: concatMap
steps$.pipe(
concatMap(step => this.api.saveStep(step))
)
Case Study 4: Prevent Double Login
Requirement: Ignore double-clicks
Solution: exhaustMap
loginClick$.pipe(
exhaustMap(() => this.api.login(credentials))
)
8. How They Behave with Timeline (Flow Examples)
switchMap Timeline
Streams: A B C
Only C completes (latest cancels previous)
mergeMap Timeline
A B C all run in parallel
Completion order unpredictable
concatMap Timeline
A finishes → B finishes → C finishes
Order guaranteed
exhaustMap Timeline
A starts
B and C ignored
After A completes, next emission accepted
9. When to Use Which Operator (Rules You Can Apply Directly)
Use switchMap when
Use mergeMap when
Use concatMap when
Use exhaustMap when
10. Final Summary
| Operator | Use When |
|---|
| switchMap | You want only the latest result |
| mergeMap | You want all results in parallel |
| concatMap | Order must be preserved |
| exhaustMap | Ignore new events until current is done |
These four operators are the backbone of advanced Angular Reactive programming.
Once you approach them with clarity, your code becomes cleaner, easier to maintain, and safer for production workloads.