Pages

Monday, July 29, 2019

Flattening in RxJS: A decent explanation (not mine)

Hey, look, a decent explanation of flattening operators in RxJS:

RxJS: Avoiding switchMap-Related Bugs

The beauty of the post is that each mapping is used within the real-world context of an online store. Which mapping is used for which buttons/interactions?

(Blockquotes are from the page linked. Example: comments are from me.)

mergeMap

For example, if the user clicks the remove buttons of the first and second items, it’s possible that the removal of the second item might occur before the removal of the first. With our cart, the ordering of the removals doesn’t matter, so using mergeMap instead of switchMap fixes the bug.

Example: Remove item from cart buttons. You don’t care if the second item that has its remove button clicked second but it’s removed first. mergeMap, just get ’er done.

concatMap

For example, if our shopping cart has a button for increasing an item’s quantity, it’s important that the dispatched actions are handled in the correct order. Otherwise, the quantities in the frontend’s cart could end up out-of-sync with the quantities in the backend’s cart. With actions for which the ordering is important, concatMap should be used.

Example: If order absolutely matters, you use concatMap. Increasing the number of an item in your cart needs to go in order. You don’t want a “1 widget” to turn into “2 widgets” by way of “3 widgets”, “4 widgets” after clicking the “add” button three times.

switchMap

If our application’s cart shows the total cost of the items plus the shipping, each change to the cart’s content would see a GetCartTotal action dispatched. Using switchMap for the effect/epic that handles the GetCartTotal action would be entirely appropriate.

Example: If only the last action matters and supersedes the previous ones, use switchMap. So if you want to refresh your the price of a user’s cart automatically, you can ignore any stale replies. Say the user changed quantity and you fire off a new “get total with shipping” request. Anything sent earlier is stale. Ignore those previous requests with switchMap.

(Obviously there are other uses of switchMap that are a little more complicated, but this is one.)

exhaustMap

If our shopping cart has a refresh button and the effect/epic that handles the refresh uses switchMap, each incessant button click will abort the pending refresh.

Example: Ah, this one is clever. Contra the switchMap, you want to only listen to the FIRST of the requests with exhaustMap – wait until the original is exhausted before sending another.

  • In switchMap, you want to ignore earlier requests because older is stale.
  • In exhaustMap, everything but the first is superfluous, and those newer requests should be ignored.

Their example is a refresh button. If nothing else on the page has changed, you don’t want to field new refresh requests. There’s no extra info. Wait for the first to come back and ignore the mad button presses, our lessons from Win95 and mouse movement be darned.