Skip to content

Commit 0bce1e5

Browse files
committed
switchvsconcatvsmerge
1 parent a5cb6a0 commit 0bce1e5

File tree

5 files changed

+34
-0
lines changed

5 files changed

+34
-0
lines changed

_chapters/functionalreactiveprogramming.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,40 @@ The advantage of this code is not brevity; with the introduced type definitions
499499

500500
As an example of *scalability* we will be using this same pattern to implement the logic of an asteroids arcade game in the [next chapter](/asteroids).
501501

502+
### MergeMap vs SwitchMap vs ConcatMap
503+
504+
In RxJS, `mergeMap`, `switchMap`, and `concatMap` are operators used for transforming and flattening observables. Each has its own specific behavior in terms of how it handles incoming values and the resulting observable streams. Here's a breakdown of each:
505+
506+
Lets consider three almost identical pieces of code
507+
508+
```javascript
509+
fromEvent(document, "mousedown").pipe(mergeMap(() => interval(200)))
510+
fromEvent(document, "mousedown").pipe(switchMap(() => interval(200)))
511+
fromEvent(document, "mousedown").pipe(concatMap(() => interval(200)))
512+
```
513+
514+
With `mergeMap`, each mousedown event triggers a new `interval(200)` observable. All these interval observables will run **concurrently**, meaning their emitted values will *interleave* in the output. In the animation, the `x2` occurs when two observables emit at a approximately the same time, and it cannot be visualized easily.
515+
516+
![Merge Map Visualized](/assets/images/chapterImages/functionalreactiveprogramming/mergeMapMouseDown.gif)
517+
518+
With `switchMap`, each time a `mousedown` event occurs, it triggers an `interval(200)` observable. If another mousedown event occurs before the interval observable finishes (interval doesn’t finish on its own), the previous interval observable is canceled, and a new one begins. This means only the most recent mousedown event's observable is active. This can be seen as the counter restarting every single time a click occurs, as our interval always emits sequential numbers.
519+
520+
![Switch Map Visualized](/assets/images/chapterImages/functionalreactiveprogramming/switchMap.gif)
521+
522+
With `concatMap`, each time a mousedown event occurs, it starts emitting values from the `interval(200)` observable. Importantly, if a second mousedown event occurs while the previous interval observable is still emitting, the new interval won't start until the previous one has completed. However, since interval is a never-ending observable, in practice, each mousedown event's observable will queue up and only start after the previous ones are manually stopped or canceled. Therefore, no matter how many times a click occurs, the next interval will never begin.
523+
524+
![Concat Map Visualized](/assets/images/chapterImages/functionalreactiveprogramming/concatMap.gif)
525+
526+
We can make an adjustment to this, where, we stop the interval after four items.
527+
528+
```javascript
529+
fromEvent(document, "mousedown").pipe(concatMap(() => interval(200).pipe(take(4))))
530+
```
531+
532+
![Concat Map Visualized w/ End](/assets/images/chapterImages/functionalreactiveprogramming/concatMap_take4.gif)
533+
534+
Unlike the previous example with a never-ending interval, in this case, each interval observable completes after emitting four values, so the next mousedown event's observable will queue up and start automatically as soon as the previous one completes. This setup ensures that each click's sequence of interval emissions will be handled one after the other, with no overlap, maintaining the order of clicks and processing each one to completion before starting the next.
535+
502536
## Glossary
503537

504538
*Asynchronous*: Operations that occur independently of the main program flow, allowing the program to continue executing while waiting for the operation to complete.
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)