switchMap 奇怪的行为

switchMap Strange Behavior

我试图理解以下代码的控制台输出。我期待它会每 500 毫秒控制台记录 0 到 9,然后再次从 0 开始(并以 9 结束)。

但事实是第一次只会console log 0-9,然后输出变成0-8,8停顿1秒,然后又从0开始。

我的问题是

  1. 为什么9只出现了一次?
  2. 为什么在 8 上有 1 秒(而不是 500 毫秒)的暂停?

由于源 Observable 每 5 秒发射一次,内部 Observable 每 500 毫秒发射一次,因此内部 Observable 应该有足够的时间发射 0 到 9,并且不应在 8 时暂停。

这是 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));

因为计时器不是那么准确,这是 NodeJS 事件循环和计时器的问题 API。

将打印 9 的最后一个间隔即将执行,但 timer(0, 5000) 已到。

你可以尝试增加 timer 一点点让 9 打印出来

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

或使用 timer 而不是 interval 以便它会立即执行以查看打印 9

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

为什么9只出现了一次?

在我的例子中,9 根本没有显示。所以我想这可能是某种时间不准确?这很紧凑 - 理论上 interval 比计时器晚一点启动。因此它只打印 9 个值 (0-8)。

为什么在 8 上有 1 秒(而不是 500 毫秒)的暂停?

8 是在 4500 毫秒打印出来的。当计时器达到 5000 毫秒(从 8 开始需要 500 毫秒)时,它会启动新的 interval。新的间隔将在另一个 500 毫秒后发出。因此这些之间有 1 秒的延迟。

如果打印了 9,我希望延迟只有 500 毫秒。但同样 - 在我的情况下 9 从未打印过。