RxJS: Exhaust map what it is and how to use
exhaustMap
is an interesting operator which is useful in some specific scenarios and at the same time may be hard to understand on graphics shown all over the internet. In this article I’m going to explain how it works and when to use it.
Let’s start with the basics. What is exhaustMap
? It is an operator that subscribes to a source observable. When it emits a value the operator should return another observable. When the returned observable completes will exhaustMap
take another emitted value from its source and repeat the process. One important note here — it will ignore all values that were emitted during the returned observable execution.
Let’s imagine this case. We have a ProfileWidget component which needs current user’s data and also ProfilePage which displays the data in a more expanded way on the page. Those two can be present on the page at the same time, therefore if we make requests in regular way they will be made twice though fetching the same data. For the sake of simplicity I will use a timer
function to simulate requests.
As was expected we observe two requests and two subscriptions logs.
Now, let’s rewrite it to use exhaustMap
.
Here we:
- create a source of events
fetchUserEvent
which will emit values each time we need to get user data - assign to
fetchUserSource
an observable made out of this source of events withexhaustMap
on it which returns same “request” in response to events - add
share
operator to make this observable multicast
When each component initializes they subscribe to the same observable and emit an event that they require new data. When we try to make 2 requests (as the result of 2 emitted events) we get only 1 response, as second event was ignored (because both events are emitted synchronously and inner observable takes 1 sec to complete).
After that, we may make other events to refresh the data and it works as expected, because the third request is made after 2 secs when the inner observable completed.
This approach also can be used in so called Effects in Redux-ish stores or even without stores when we need to share a response and at the same time we don’t want to have same concurrent requests.