Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding SwitchMap in rxjs

as per the definition of the switchMap

On each emission the previous inner observable (the result of the function you supplied) is cancelled and the new observable is subscribed. You can remember this by the phrase switch to a new observable.

now, i have a code like this

const source = timer(0, 5000).pipe(map(x=>`${x}`));
const example = source.pipe(switchMap((f) => interval(1000).pipe(map(y=>`f${f}-s${y}`))),take(20));
const subscribe = example.subscribe(val => console.log(val+' '+ new Date().getSeconds()));

and the result is this

enter image description here

my question is,

  1. 25th second - the outer function is called and the inner function is not yet triggered, so the latest value of the outer function is 0 and inner function is also 0 as a default one because it has no value yet f0-s0 25

  2. 26th second - the inner function is called and the value ideally should be 0 as the function is just called first time but it is 1 ie. f0-s1 26

  3. 30th second - the outer function is called which resets the inner function value to 0, ie. f1-s0 30

  4. why is the inner function got reset on the 35th second, it is still 1 second remaining

stackblitz link

i find it very difficult to understand the concept, thank you

like image 897
Lijin Durairaj Avatar asked Dec 23 '22 23:12

Lijin Durairaj


2 Answers

This is because RxJS by default for async actions uses setTimeout and setInterval function that don't guarantee they'll make exactly the timeout you want.

So if you use timeouts 5000 and 1000 then it's not guaranteed which of the actions will happen first after 5s. Sometimes the outer Observable emits first and sometimes the inner emits first but switchMap can't do anything about it.

You can see how different the times can get with eg. this:

const start = new Date().getTime();
setInterval(() => console.log(new Date().getTime() - start), 1000);

Live demo: https://stackblitz.com/edit/typescript-urep5j

1004
2001
3002
4000
4998
...

So sometimes the delay is 1004 and other times just 998.

like image 178
martin Avatar answered Dec 25 '22 22:12

martin


I think, you're wrongly assuming that your source started emitting at 25s second, while it started at 24s. And theres no "default 0".

Source emits at t0, then in 1s inner interval will emit. Inner interval will have 5 seconds to emit 4 or 5 times, before you'll switch to another value from the source timer. If your source timer started emitting at 24s, then first value you'll get on the subscription is at 25s — when the interval will emit its first value.

The reason for 4 or 5 time is in RxJS and JS scheduling. See this stackblitz for a rough example of what might be going on. Explaining this in detail would take more research effort and time.

Heres a marble diagram picturing mergeMap vs exhaustMap vs switchMap vs concatMap behavior to get a better understanding:

mergeMap vs exhaustMap vs switchMap vs concatMap

Check this mergeMap vs exhaustMap vs switchMap vs concatMap playground.

like image 29
kos Avatar answered Dec 25 '22 23:12

kos