DATEV Nine-Nine | Flattening Operators
By: Matthias Alt, Stephan Bierwirth und Gerrit Riesch
We all know it can be difficult to remember the exact behavior of each RxJS Flattening Operator. Therefore, we are going to compare the four operators to four detective types. With each detective working their cases in a similar style as a particular Flattening Operator we hope to provide you with a nice and easy way to memorize them. For us it certainly worked. ;)
Flattening operators — Almost every Angular App uses them and they are the default way in RxJS for dealing with higher order Observables, i.e., Observables of Observables. So far so good. That’s the way to get the inner Observable and solve the “problem” of processing Observables of Observables. The most difficult part is often to decide which flattening operator suits our needs best. We took a look at our detective squad and noticed that some detectives are working their cases very similar to the way a given Flattening Operator is handling it’s arriving values. In the following examples each case that arrives at the detective’s desk is equivalent to the emitted value of an inner observable.
mergeMap() — The “Jake”
Let’s start with Jake. He’s the star of the precinct but he might take on a little much at times. He takes all the cases he can get his hands on, and he works them all simultaneously. That way he finishes a lot of cases in parallel, but he might cause some chaos in the process.
When to use: If you have for example some HTTP requests coming in and you want to process them all, but order doesn’t concern you. This can be the case for write operations (in contrast to read where cancellation of previous requests wouldn’t be a problem).
switchMap() — The “Hitchcock”
Then there is Hitchcock. He has a very short attention span and is not ambitious to finish his cases. He takes a new case if one arrives, but he doesn’t really care if he has finished the previous one. So, he drops any current case as soon as a new one comes in and he takes that new one. The new case could be more interesting after all.
When to use: You have an input field and want to offer an autocomplete feature? Then `switchMap` is a well-fitted solution. In combination with a `debounceTime` operator you can achieve a nice user experience while sending only requests really necessary to get your autocomplete options.
exhaustMap() — The “Terry”
Our next detective — let’s call him “Terry” — is a decent and friendly teamplayer. He looks out for his detective squad and always finishes what he starts. Therefore, he only takes one case at a time, and he will take on no new case until he has finished his current one. Focus is his mantra.
When to use: When you have to ensure something is only executed once, e.g., saving information given by your user in your backend application, `exhaustMap` is the operator of choice.
concatMap() — The “Amy”
We all know that kind of person who finishes all the work given to them no matter what. Amy will take on all new cases that are arriving at her desk. Nevertheless, she will always finish the current case first before starting the next one. But no matter how much workload has piled up she will always take on any new case that may arrive at her desk and finish them one after another.
When to use: If you have requests coming in and you want to process them all and order does matter.
We hope our detective analogy will help you in your upcoming flattening “cases”. For a detailed description and introduction to RxJS we recommend Introduction — Learn RxJS and the (German) Book “Angular — Grundlagen, fortgeschrittene Themen und Best Practices”, especially chapter “Reaktive Programmierung mit RxJS”.