HFrost
HFrost

Reputation: 67

switchMap Strange Behavior

I am trying to understand the following code's console output. I was expecting it will console log 0 through 9 every 500ms and then start over with 0 again (and end up with 9).

But the fact is it would only console log 0-9 the very first time, and then the output became 0 - 8, with a 1 second pause on 8, and then start with 0 again.

My question is

  1. Why 9 only showed up once?
  2. Why there's a 1 second (instead of 500ms) pause on 8?

Since the source observable emits every 5 secs and inner observable emits every 500ms, it should have enough time for the inner observable to emit 0 to 9, and it should not pause on 8.

Here is the same code on stackblitz: https://stackblitz.com/edit/typescript-eb62ap?file=index.ts&devtoolsheight=100

// RxJS v6+
import { timer, interval } from 'rxjs';
import { switchMap } from 'rxjs/operators';

//emit immediately, then every 5s
const source = timer(0, 5000);
//switch to new inner observable when source emits, emit items that are emitted
const example = source.pipe(switchMap(() => interval(500)));
//output: 0,1,2,3,4,5,6,7,8,9...0,1,2,3,4,5,6,7,8
const subscribe = example.subscribe(val => console.log(val));

Upvotes: 0

Views: 238

Answers (2)

Martin Nuc
Martin Nuc

Reputation: 5764

Why 9 only showed up once?

In my case 9 is not shown at all. So I guess it could be some kind of time inaccuracy? This is tight - theoretically interval starts little bit later than timer. Therefore it prints only 9 values (0-8).

Why there's a 1 second (instead of 500ms) pause on 8?

The 8 is printed at 4500ms. When timer reaches 5000ms (which takes 500ms since 8) it spins up the new interval. The new interval will emit after another 500ms. Therefore 1s delay between these.

If there's 9 printed I would expect delay to be only 500ms. But again - in my case 9 is never printed.

Upvotes: 1

Timothy Lee
Timothy Lee

Reputation: 828

Because timer is not that accurate, that's the problem of NodeJS event loop and timer API.

the last interval which will print 9 is about to execute but timer(0, 5000) has reached its time.

You could try increase timer just a little bit to let the 9 printed out

const source = timer(0, 5100); //add some time
const example = source.pipe(switchMap(() => interval(0,500)));

or use timer instead of interval so that it will execute without delay to see the 9 is printed

const source = timer(0, 5000);
const example = source.pipe(switchMap(() => timer(0,500))); //use timer

Upvotes: 2

Related Questions