按照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()));
结果就是这个
我的问题是
第25秒-调用了外部函数并且尚未触发内部函数,因此外部函数的最新值为0,并且内部函数的默认值为0,因为它尚无值< strong> f0-s0 25
第26秒-调用内部函数,并且理想情况下该值应为0,因为第一次调用该函数时应为1,即。 f0-s1 26
30秒-调用外部函数,它将内部函数值重置为0,即。 f1-s0 30
为什么内部函数在第35秒被重置,仍然剩余1秒
我很难理解这个概念,谢谢
答案 0 :(得分:5)
这是因为默认情况下,用于异步操作的RxJS使用setTimeout
和setInterval
函数,这些函数不能保证它们会完全满足您的超时要求。
因此,如果您使用超时5000
和1000
,则不能保证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 playground。