【问题标题】:Understanding SwitchMap in rxjs理解 rxjs 中的 SwitchMap
【发布时间】:2019-04-05 08:09:37
【问题描述】:

根据switchMap的定义

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

现在,我有这样的代码

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

结果是这样的

我的问题是,

  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

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

【问题讨论】:

  • 除了@martin 的回答解释了34s39s 的差距之外,我认为,您还错误地假设您的源在25th 秒开始发射,而它开始在24s。没有“默认 0”,它是从 24s 开始的源,并且间隔首先在 25s 发射。

标签: javascript rxjs reactive-programming rxjs6 switchmap


【解决方案1】:

这是因为 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

【讨论】:

  • 所以在 switchMap 中,每当调用外部函数时,内部函数值都会被重置,我的理解对吗?如果可能的话,你能制作一个弹珠汤姆帮助人们了解 switchMap,像这样吗?observable-playground.github.io/gist/…
  • @LijinDurairaj 这显示了switchMap 的作用reactivex.io/rxjs/img/switchMap.png
  • 我刚刚发现了这个,rxmarbles.com/#switchMap,根据这个弹珠,switchMap只有在外部函数发出一个值并且重置整个内部函数值时才会发出一个值,我的理解是否正确,如果我错了,请纠正我
  • 我认为,这里的特殊问题不是 JS 调度程序缺少 1s 间隔,而是 RxJS 交替使用 setIntervalsetTimer 的方式以及这些异步任务在 JS 中的优先级方式环境。当 JS 调度程序检查其任务列表时——它将运行 所有设置的计时器和间隔,但执行顺序将取决于设置的方式和时间 .继承人 stackblitz example 在后续调用中交换订单
  • @LijinDurairaj,“重置内部功能”并不是考虑switchMap 的最佳方式。所有__Map 运算符将源流上的值替换为由内部函数返回的值流。不同之处在于对源流上的后续值的反应。 switchMap 将取消订阅先前交换的流并使用由内部函数生成的新流。
【解决方案2】:

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

源在t0 发射,然后在1s 内部interval 将发射。在您从源 timer 切换到另一个值之前,内部 interval 将有 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 playground

【讨论】:

  • 你所有使用弹珠的例子都非常有帮助,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-14
  • 2019-10-12
  • 1970-01-01
  • 1970-01-01
  • 2018-09-16
相关资源
最近更新 更多