Sunday, November 7, 2021

RxJS - exhaustMap and switchMap

 

Unlike using concatMap or mergeMap, we might want to cancel the previous transformed Observable if the next value arrived or we like to ignore the next transformed Observable if the previous transformed Observable has not been completed.


exhaustMap



Transform each value of source Observable to a new (inner) Observable, and the emitted values of those new (inner) Observables will be merged to the output Observable. But if the previous transformed (inner) Observable has not completed yet, then the new transformed Observable by new emitted value of source Observable will be ignored. 


This is the marble diagram from 
RxJS official Doc.


Ex: Ignore the new click event if the corresponding tasks of the previous click event has not been finished.

 
// Use it to track the emitted value from click event
let index = 0;

// Click event
fromEvent(document, 'click')
.pipe(
// Logging the # of click event
tap(() => console.log('click event #' + index)),
// Map it to #
map(() => index),
// Increasing #
tap(() => index++),
// Using exhaustMap to transform and subscribe all source Observable
// only if the previous transformed observable is completed.
// Also, we make 2 second delay to simulate a http call
exhaustMap(next => of(next).pipe(delay(2000)))
)
// Subscribe it and logging the emitted value
.subscribe(console.log);


Result:


click event #0
click event #1
click event #2
0



From this experiment, we click the page three times, and only the first click event will be transformed and subscribed to.




Transform each value of source Observable to a new (inner) Observable, and the emitted values of those new (inner) Observables will be merged to the output Observable. But if there is a new emitted value from source Observable, and the previous transformed (inner) Observable has not been completed yet, then switchMap will unsubscribe the previous transformed Observable, and subscribe the new transformed Observable. 


This is the marble diagram from RxJS official Doc.

Ex: Cancel the previous click event if the corresponding tasks has not been finished when there is a new coming click event.

 
  // Use it to track the emitted value from click event
let index = 0;

// Click event
fromEvent(document, 'click')
.pipe(
// Logging the # of click event
tap(() => console.log('click event #' + index)),
// Map it to #
map(() => index),
// Increasing #
tap(() => index++),
// Using switchMap to transform and subscribe all source Observable
// But the previous transformed Observable will be unsubsribed
// if there is a new emitted value from source Observable
// Also, we make 2 second delay to simulate a http call
switchMap(next => of(next).pipe(delay(2000)))
)
// Subscribe it and logging the emitted value
.subscribe(console.log);


Result:


click event #0
click event #1
click event #2
2



From this experiment, we click the page three times, and only the last click event will be transformed and subscribed. The previous two (#0 and #1) will be subscribed but unsubscribed later since there is a new emitted value from source Observable.

No comments:

Post a Comment