Be the first user to complete this post

  • 0
Add to List

The difference between switchMap and flatMap or mergeMap

switchMap and mergeMap are probably going the be the most powerful and frequently used operators in your arsenal. Its is thereby critical to understand the difference between the two in order to spend less time debugging code. Both switchMap and mergeMap are used to flatten observables. mergeMap is also known as flatMap, however throughout this article, I will be be referring to it as mergeMap. TIP> I usually like runing my examples in the browser console of http://reactivex.io/rxjs/. The added advantage is that I get some nice autocomplete for looking up method names. The easiest way to remember the difference between mergeMap and switchMap is

When you hear the word merge, think - use everything on all the streams aka. merge everything. Whereas when you hear the word switch, think - switch to using data on the newer stream
The difference is subtle yet important. Lets demonstate with some examples.

mergeMap

var outer = Rx.Observable.interval(1000).take(2);

var source = outer.mergeMap(function (x) {
  return Rx.Observable.interval(500).take(3).map(y => `${x}:${y}`)
});

source.subscribe(d => console.log(d));

Marble diagram

// Marble Diagram
/*
source: -0-------1|
          \       \
inner2:    \       0---1---2|
            \
inner1:      0---1---2|

    mergeMap()

output: -----x---x-x-x-x---x|
*/
There are few things to remember here. 1) We are returning an observable stream from within an operator function. Thats precisely why we need to flatten using mergeMap (and as we will see later, switchMap). 2) Two inner streams are emitting data concurrently. One stream starts after the other. 3) Data is available on the ouput corresponding to EVERY value emmitted on ALL the inner streams. i.e. No data is ever lost. Keeping these three points in mind, now lets rewrite the above example using switchMap

switchMap

var outer = Rx.Observable.interval(1000).take(2);

var source = outer.switchMap(function (x) {
  return Rx.Observable.interval(500).take(3).map(y => `${x}:${y}`)
});

source.subscribe(d => console.log(d));

Marble diagram

// Marble Diagram
/*
source: -0-------1|
          \       \
inner2:    \       0---1---2|
            \
inner1:      0---1---2|

    switchMap()

output: -----x-----x---x---x|
*/
Notice this time how the output has far fewer data points. Thats because the moment the inner2 stream became available, the output no longer listens to data from inner1. switchMap effectively switches over to inner2 and unsubscribes from the previous one. This also implies that even though the inner streams may be producing data concurrently in switchMap, the output is only determined by the latest observable that is still producing data. Hope this simplifies your understanding of these two operators.



Also Read:

  1. The difference between Rxjs combineLatest and withLatestFrom
  2. Getting started with Rxjs and streams
  3. Rxjs Observable publish refcount vs share
  4. Difference between Rxjs Subject and Observable