RxJS

RxJs SwitchMap Operator: How Does It Work?

Although RxJs has a large number of operators, in practice we end up using a relatively small number of them. And right after the most familiar operators that are also available in arrays (like map, filter, etc.), probably the first operator that we come across that is not part of the Array API but

RxJs SwitchMap Operator: How Does It Work? — RxJS article by Angular University on Angular In Depth
RxJs SwitchMap Operator: How Does It Work? — RxJS article by Angular University on Angular In Depth
On this page · 10 sections

RxJs ships with a vast catalog of operators, yet most real-world applications tend to rely on a surprisingly small subset of them.

After the array-like operators such as map and filter, one of the first non-array operators developers encounter—and quickly come to depend on—is switchMap.

Rather than diving straight into theory, let's observe how the operator behaves in practice across two distinct stream categories:

  • short-lived streams like HTTP requests, which produce exactly one value and then terminate
  • long-lived streams such as those supplied by AngularFire, an Angular library for Firebase's real-time database and authentication services

We will conclude by examining a frequent, but less obvious, application: merging the emissions of several Observables into a single output.

Suggested Reading

For an exhaustive comparison of the switchMap, mergeMap, concatMap, and exhaustMap operators, refer to:

Comprehensive Guide to Higher-Order RxJs Mapping Operators: switchMap, mergeMap, concatMap (and exhaustMap).

Recreating HTTP and Firebase Observable Patterns

To isolate the core mechanics of the operator, we'll define a few helper functions that mimic the stream patterns commonly found in applications.

  • Cold, single-emission, short-lived streams, analogous to Angular's HTTP layer
  • Cold, multi-emission, long-lived streams, akin to AngularFire's data feeds

Understanding these foundational stream types is a prerequisite for mastering switchMap, so let's examine them closely.

The Lifecycle of Angular HTTP Observables

Let's begin by emulating the Observables returned by Angular's HTTP client, often the first streams a beginner encounters.

These Observables are distinguished by a few specific characteristics that are not universal:

  • they are cold (deferred), meaning no values are produced until a subscriber is attached
  • they emit either a single value or an error, followed by a completion signal, so they are short-lived
  • explicit unsubscription is unnecessary in most cases because the stream completes on its own

Building a Mock HTTP Request Stream

Given these traits, here is a factory function that produces Observables with identical behavior:

Within it, the of utility is employed to create an "emit once and done" stream, and the delay operator is piped in to simulate network latency.

Let's verify this function by creating two Observables that mimic separate HTTP calls:

Both Observables are cold, so they stay inert until subscribed. We'll subscribe to each and observe the console output:

A Compact Logging Pattern for Testing

Note the concise subscription syntax used here. The http1$ subscription is functionally identical to:

This shorthand works by passing console.log and console.error directly as callbacks, instead of writing anonymous arrow functions. It's a handy trick for quick debugging. Let's see the output:

1
http1$ completed
2
http2$ completed

The result is typical of Angular HTTP Observables: a single value (or possibly an error) is emitted, and then the stream completes immediately.

First Look at Switch Map

Now, let's put switchMap to work by chaining two dependent HTTP requests.

The scenario: we need to save a user's data on the server, and then fetch a secondary dataset affected by that save.

The simulation might look like this:

Let's walk through the program's output:

simulating HTTP requests
user saved 
data reloaded 
completed httpResult$

From this example, we can extract the fundamental mechanics of switchMap in action:

  • The saveUser$ Observable acts as the source
  • The stream resulting from switchMap is the resultObservable$
  • without a subscriber, the resultObservable$ remains dormant
  • subscribing to it creates a subscription to the saveUser$ source
  • when the source emits, the value flows into the function provided to switchMap
  • that function must return an Observable, which may or may not use the source value
  • this returned Observable is the inner Observable
  • the inner Observable is subscribed to, and each of its emissions is also emitted by the result observable
  • the result observable completes only when the source completes

This pattern is ideal for orchestrating a second request based on the primary request's result—a common workflow. However, this simple example leaves questions unanswered, particularly regarding the operator's naming.

Deconstructing the SwitchMap Name

A name often clarifies a concept. Let's scrutinize the two parts of this operator's name:

  • what exactly is being switched, and from what to what?
  • what is being mapped in this context?

One might assume the "switch" occurs from the source Observable to the inner Observable. As we'll see, that's not the case.

The "map" part is often easier to intuit; it refers to the act of mapping the emitted source value into a brand new Observable.

Let's now identify the true target of the "switch".

The Need for Longer-lived Streams

The HTTP-like streams we've explored so far, while useful, make it hard to appreciate the full power of switchMap. Since they emit once and complete, the operator's dynamic nature is obscured. To truly observe it in action, we need streams that emit multiple times—the AngularFire-like variety.

Simulating AngularFire's Data Streams

We'll create a new utility function to generate these long-lived Observables:

Let's use it to create two Observables that mimic Firebase's real-time data feeds:

Characteristics of the Firebase-like Streams

What sets these streams apart? Let's analyze the output of our simulation above:

1:  FB-2  0
2:  FB-2  1
3:  FB-2  2
4:  FB-2  3
5:  FB-1  0
6:  FB-2  4
7:  FB-2  5
8:  FB-2  6
9:  FB-2  7
10: FB-2  8
11: FB-1  1
12: FB-2  9
...

Long-lived vs. Short-lived

The behavior is distinctly different from the HTTP streams we've seen. Let's break it down, starting from the bottom up:

  • the immediate and obvious difference is that these streams don't complete; they persist and keep emitting values
  • the stream will continue pushing new values indefinitely until an unsubscribe action is taken
  • firebase2$ has a 1-second interval, thus a higher emission frequency
  • the firebase1$ stream, with a 5-second interval, produces fewer values in the same timeframe.

The Inner Workings of SwitchMap, Revealed

With these long-lived streams, we can now observe what switchMap truly does. Let's chain these two streams together and predict the output:

We'll wire them up like this—with some indentation added to the output for clarity:

source value FB-1  0
    inner observable  0
    inner observable  1
    inner observable  2
    inner observable  3
source value FB-1  1
    inner observable  0
    inner observable  1
    inner observable  2
    inner observable  3
source value FB-1  2
    inner observable  0
    inner observable  1
    inner observable  2
...

The Origin of the "Switch"

Let's dissect this output to see why switch is part of the name:

  • as before, no output is generated until the result observable is subscribed to
  • the source stream emits its first value, FB-1 0
  • this value is mapped to an inner observable using our function
  • the inner observable is then subscribed to
  • the result observable dutifully reflects the emissions of the inner stream
  • notice the inner stream starts at 0, emitting values from a newly created interval

The Meaning of Switch in this Context

Here's where things diverge from the HTTP example. Since the source stream is long-lived, it eventually emits a second value, FB-1 1.

The moment this new value arrives, the behavior changes dramatically:

  • the previously active inner observable, which was about to emit index 3, is silently abandoned
  • our mapping function is invoked again, generating a fresh, brand new inner observable
  • this new inner observable is subscribed to
  • the new inner observable begins its emission sequence from index 0
  • the result observable now emits values from this new inner observable, having forgotten the old one

But What Actually Happened to the Old Stream?

The original inner observable wasn't paused. It was unsubscribed from, discarding its future values.

The result observable performed a switch. Its allegiance moved from the original inner observable to the newly minted one.

This single `switch` operation defines the very essence of the switchMap name.

SwitchMap, Condensed

To summarize: switchMap listens to a source Observable. For each value it receives, it creates a new inner Observable. It subscribes to this new inner Observable and emits its values downstream.

A source emission triggers a cancellation: the previous inner Observable is unsubscribed, and the focus shifts entirely to the new one. It is crucial to understand that the source Observable itself is never cancelled, only those transient inner Observables.

That's the whole story—the name, the mechanism, and the primary use case. But there is a lesser-known benefit that makes this operator even more valuable.

Combining Emissions from Multiple Observables

Imagine you need the final value to include data from both the source and the inner Observable. This isn't about replacing one with another.

Instead, you can merge them into a single output. A simple way is to use the map operator inside switchMap's function to combine the values into a single structure, like a tuple:

Observing the Combined Output

Let's examine the console. The result observable is no longer emitting a single value. Instead, it emits a combination:

[Object, Array(30)]

The final output objects are plain JavaScript arrays. Inside, we see:

  • the first entry is a course object, coming from the initial HTTP request (the source)
  • the second entry is an array of lessons, which originates from the inner Observable

Wrapping Up

The switchMap operator is a cornerstone of many RxJs applications. A solid grasp of its mechanics will help you implement complex, asynchronous workflows with confidence.

You will likely find yourself using it in nearly every project you build.

I hope this exploration clarifies how it operates. To stay informed when further articles on popular RxJs operators are released, consider subscribing to our newsletter:

For a deeper dive into RxJs, we recommend our RxJs In Practice Course. It provides numerous practical patterns and detailed explanations of many operators.

If you are new to Angular itself, you might find the Angular for Beginners Course to be a helpful starting point:

RxJs SwitchMap Operator: How Does It Work? — figure 1

Further Reading on Angular

Here are other posts you may find useful:

AU
Angular University

Writes about RxJS, Components, Signals. Active 2015–2026.

All 79 articles →