Demo: exhaustMap
exhaustMap => map + exhaust (discard) the new task if an earlier task is still in-progress.
The exhaustMap maps the source items to tasks for execution but, discards them if they arrive when a task for an earlier item is still in progress.
It is useful where the concurrent requests are considered as duplicate or redundant requests, which need to be discarded. It's just the complementary behaviour of switchMap.
const source=timer(500,2500).pipe(take(4));
//1. Each input from source maps to this counting task
const countTill2Task = timer(0,1700).pipe(take(3)
//2. exhaustMap discards the execution of any concurrent task
const mapAndExhaust = exhaustMap(v => countTill2Task );
const output = source.pipe(mapAndExhaust)
.subscribe(v=>console.log(v))
The exhaustMap is a combination of the map and the exhaust all operator.
- To start with, the map part maps each of our source items to an observable that specifies our intended task.
- Then, it submits them for execution by exhaustAll operator.
- Then exhaustAll, always discards the newly arrived task, if an earlier task is still in-progress.
Well, this is useful when the concurrent inputs represent duplicate or redundant tasks, which need to be discarded.
Let's understand it further with the demo on exhaustMap:
- On the first part, we map each of our input to a count till 2 task.
- But, execution part, discards these tasks, if an earlier count till 2 task is still in-progress. As a result, in the output of the demo, we can see:
- The exhaustMap discarded the count task for 1, because it arrived when the count task for 0 was in-progress.
- Similarly, it discarded the count task for 3, because it arrived when the count task for 2 was in-progress. Avoiding duplicate or redundant concurrent requests is a key feature of this exhaustMap operator. We will look at more of it's usages later in the post.
The exhaustMap is useful where the concurrent requests are considered to be duplicate or redundant requests, hence, they are supposed to be discarded.
Use Case 1. Discard concurrent save requests.
Let's say we have a save feature in an online editing software.
When a user is trying to save, there is no point sending multiple save requests to the server. But, incase the saving is taking bit longer and the user is trying to save multiple times, we can use exhaustMap to discard any concurrent save requests.
Thus, as long as an earlier save request is still in-progress, any new save request by the user will be discarded.
Output : On multiple clicks to save the document.
New Save Request...
saving doc...
New Save Request...
New Save Request...
New Save Request...
done !
New Save Request...
saving doc...
New Save Request...
done !
For an on-going request, exhaustMap discards all new concurrent save requests.
Use Case 2 : Discard duplicate login requests
Very similar to the above case, let's say an user is trying to login and has submitted login request multiple times as the server is not responding fast.
Unless we discard the folllow up login request, we might unnecessarily lock the user for multiple attempts, if his credentials were wrong.
So, in such case we can make use of exhaustMap to discard the concurrent, duplicate requests.