🅰️ Angular Q63 / 125

Difference between mergeMap, switchMap, and concatMap?

AI-Powered Answer ✓ Answered

RxJS mapping operators transform values emitted by a source observable into new observables, and then flatten these 'inner' observables back into a single output stream. `mergeMap`, `switchMap`, and `concatMap` are three fundamental flattening operators, each with distinct behaviors regarding how they handle concurrent inner observables.

mergeMap

The mergeMap operator (also known as flatMap) subscribes to all inner observables that are created and emits all values from every inner observable as they arrive. It essentially 'merges' the output of all concurrently active inner observables into a single stream. It does not cancel previous inner observables.

  • Handles multiple concurrent inner observables.
  • Order of emitted values from inner observables is not guaranteed (depends on completion timing).
  • Suitable for operations that can run in parallel without conflict, e.g., fetching multiple resources simultaneously.
typescript
import { of, mergeMap, delay } from 'rxjs';

of(1, 2, 3).pipe(
  mergeMap(val => of(`Value: ${val}`).pipe(delay(Math.random() * 100)))
).subscribe(console.log);
// Possible output: 'Value: 2', 'Value: 1', 'Value: 3' (order can vary)

switchMap

The switchMap operator unsubscribes from the previously projected inner observable whenever the source observable emits a new value. It effectively 'switches' to the new inner observable, canceling any previous, ongoing inner observables. Only values from the most recent inner observable are emitted.

  • Unsubscribes from previous inner observables when a new one is created.
  • Guarantees that only values from the most recent inner observable are processed.
  • Ideal for operations where only the latest request is relevant, e.g., typeaheads or search queries.
typescript
import { fromEvent, switchMap, debounceTime, of, delay } from 'rxjs';

const searchInput = document.getElementById('search-input');
fromEvent(searchInput, 'input').pipe(
  debounceTime(300),
  switchMap((event: any) => of(`Searching for: ${event.target.value}`).pipe(delay(500)))
).subscribe(console.log);
// Only the result for the last typed value will be logged.

concatMap

The concatMap operator maps each value from the source observable to an inner observable, then subscribes to and waits for each inner observable to complete before subscribing to the next one. It processes inner observables sequentially, ensuring the order of execution and emission based on the source observable's values.

  • Processes inner observables one after another, in sequence.
  • Waits for each inner observable to complete before starting the next.
  • Guarantees the order of emitted values will match the source observable's order.
  • Useful for operations that must happen strictly in order, e.g., sequential API calls where one depends on the previous.
typescript
import { of, concatMap, delay } from 'rxjs';

of(1, 2, 3).pipe(
  concatMap(val => of(`Processing: ${val}`).pipe(delay(100)))
).subscribe(console.log);
// Output: 'Processing: 1', 'Processing: 2', 'Processing: 3' (always in order)

Comparison Summary

FeaturemergeMapswitchMapconcatMap
ConcurrencyConcurrentLatest onlySequential
OrderNot guaranteedLatest onlyGuaranteed (source order)
CancellationNoYes (previous)No
Use CaseParallel tasksTypeaheads, latest dataOrdered sequential tasks

When to Use Which

When to Use mergeMap

mergeMap is best when you need to perform multiple independent operations in parallel, and you want to collect all their results as they become available. For example, fetching details for a list of IDs where the order of results doesn't matter, or sending multiple log events to a server.

When to Use switchMap

switchMap is ideal when you only care about the result from the most recent request and want to discard previous, ongoing requests. Common scenarios include search auto-completion, filtering lists based on rapidly changing input, or cancelling an old HTTP request if a new one is initiated.

When to Use concatMap

concatMap is essential for operations that must execute strictly in sequence, where the order of operations and their completion is critical. This includes scenarios like saving multiple items to a database one by one, ensuring each save completes before the next begins, or performing a series of interdependent API calls.