了解rxjs中的SwitchMap

时间:2019-04-05 08:09:38

标签: javascript rxjs reactive-programming rxjs6 switchmap

按照switchMap的定义

  

在每次发射中,先前的内部可观测值(   您提供的功能)被取消,新的可观察到的是   已订阅。您可以通过切换到新词组来记住这一点   可观察的。

现在,我有这样的代码

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()));

结果就是这个

enter image description here

我的问题是

  1. 第25秒-调用了外部函数并且尚未触发内部函数,因此外部函数的最新值为0,并且内部函数的默认值为0,因为它尚无值< strong> f0-s0 25

  2. 第26秒-调用内部函数,并且理想情况下该值应为0,因为第一次调用该函数时应为1,即。 f0-s1 26

  3. 30秒-调用外部函数,它将内部函数值重置为0,即。 f1-s0 30

  4. 为什么内部函数在第35秒被重置,仍然剩余1秒

stackblitz link

我很难理解这个概念,谢谢

2 个答案:

答案 0 :(得分:5)

这是因为默认情况下,用于异步操作的RxJS使用setTimeoutsetInterval函数,这些函数不能保证它们会完全满足您的超时要求。

因此,如果您使用超时50001000,则不能保证5秒后会先执行哪个操作。有时外部Observable首先发出,有时内部首先发出,但是switchMap对此无能为力。

例如,您可以看到不同的时代会如何变化。这个:

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

实时演示:https://stackblitz.com/edit/typescript-urep5j

1004
2001
3002
4000
4998
...

因此我们可以认为延迟为1004,而其他时间仅为998

答案 1 :(得分:2)

我认为,您错误地假设源在25s秒开始发射,而源在24s开始发射。而且没有“默认0”。

源在t0发射,然后在1s内部interval发射。在您从来源interval切换到另一个值之前,内部timer将有5秒的时间发出4次 5次。如果您的来源timer开始在24s发射,那么您将在订阅中获得的第一个值是25s-当interval将发射其第一个值时。

4次 5次的原因是在RxJS和JS调度中。请参阅此stackblitz for a rough example可能发生的情况。对此进行详细解释将需要更多的研究工作和时间

这里有一张描绘mergeMap vs exhaustMap vs switchMap vs concatMap行为的大理石图,可以使您更好地理解:

mergeMap vs exhaustMap vs switchMap vs concatMap

选中此mergeMap vs exhaustMap vs switchMap vs concatMap playground