了解rxjs中的SwitchMap

问题描述 投票:3回答:2

根据switchMap的定义

在每次发射时,前一个内部observable(您提供的函数的结果)被取消,并且新的observable被订阅。您可以通过短语切换到新的可观察对象来记住这一点。

现在,我有一个像这样的代码

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作为默认值,因为它没有值f0-s0 25
  2. 第26秒 - 内部函数被调用,理想情况下该值应为0,因为函数刚刚被调用,但它是1即。 f0-s1 26
  3. 第30秒 - 调用外部函数,将内部函数值重置为0,即。 f1-s0 30
  4. 为什么内部函数在第35秒重置,它仍然是1秒

stackblitz link

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

javascript rxjs reactive-programming rxjs6 switchmap
2个回答
1
投票

我想,你错误地假设你的源码开始在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


4
投票

这是因为默认情况下,异步操作的RxJS使用setTimeoutsetInterval函数,这些函数不能保证它们能够完全实现所需的超时。

因此,如果您使用超时50001000,则无法保证哪些操作将在5s后首先发生。有时外部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

© www.soinside.com 2019 - 2024. All rights reserved.