Use RxJS exhaustMap to Wait for Open Combos to Finish Before Starting New Ones

Rares Matei
InstructorRares Matei
Share this video with your friends

Social Share Links

Send Tweet

In this lesson, we'll be looking at an issue with our combo implementation: given that we're switchMapping to a new inner combo each time the user presses the combo initiation key (the letter "a" in our example), if the initiation key is found anywhere in the middle of the combo, it will just cancel out any on-going inner combos.

To fix it, we'll look at the differences between switchMap and exhaustMap and why exhaustMap is a much better choice for our scenario: switchMap disposes of any previous inner observables when it gets a new notification from the source, while exhaustMap waits for the inner observable to finish, before considering any new notifications from the source.

Instructor: [0:00] But there's still a problem with our implementation. Let's change the combo to have the initiator, the letter A somewhere in the middle as well. Now to trigger the combo, we need to press the letters A, S, A, and finally F. I'll switch to the app. The timer starts. I press the letters A, S, A, and then F.

[0:23] It keeps going. It doesn't complete even though we typed the letters in the required amount of time. Why is that? Well, this observable fires whenever the combo initiator is pressed. In our case, the combo initiator is the letter A. When A is pressed, the inner combo starts. We then press S which goes through this and it's all good.

[0:42] Then when we press A again, this oper observable fires. Because of how switchMap works, it's going to immediately dispose of this inner observable and just start a brand-new combo. If we have the combo initiator anywhere else in our combo, this will never work.

[0:58] To fix it, I'll replace our switchMap with an exhaustMap. What exhaustMap does is it ignores any notifications from the source until its inner observable has completed. Now when we press the letter A, the inner combo will activate.

[1:13] Once this is active, any notifications from the source will be ignored until one of these takes ends the inner combo and we're ready to start listening for a new combo. Let's try that out. The timer starts. I'll press A, S, A and then F and it completes. Nice, it works.

[1:31] Let's use this to disable our spinner. I'll remove our debug element. I'll export the function. I'll now go back to our task progress service and import our key combo function from our event combo package.

[1:46] I'll define a new observable called hide spinner combo. It's going to be a key combo of the letters, Q, W, E, R, T, Y. Our requirement was that we need to disable the spinner completely when the combo is triggered. It's not enough to just add it to this takeUntil. We need to add it right at the tail.

[2:07] I'll do another takeUntil hide spinner combo. Whenever this is triggered, it's going to completely dispose of everything above it. Once this fires, the spinner should get disabled forever.

[2:19] If I switch back to the app, I'm going to trigger a task. I'll start typing in my combo and the moment I press Y, the spinner hides. If I try to trigger more tasks, we can see that the spinner doesn't even show at all because it's been disabled.