我有一个事件发射器,它可以相当快地发射事件,有时在同一滴答中会发射多个事件。当我从此发射器创建可观察对象并使用switchMap
时,我得到一些奇怪的行为,其中n
的值进入switchMap
,但只有1个出现。这是一些简化的代码:
const e = new EventEmitter();
const s = fromEvent<ConfigurationUpdatePayload>(
e,
'updated'
).pipe(
take(4),
map(() => Math.random() > 0.3 ? 1 : 2),
tap(v => console.log('pre', v)), //pre log
switchMap(async (i) => [
await Promise.resolve((i + 1) === 2),
i
] as const),
tap(v => console.log('post', v)), //post log
filter(([f,]) => f),
map(([, p]) => p)
);
s.subscribe(v => console.log('result', v));
for (let i = 0; i < 4; i++) {
e.emit('updated', 1);
// await new Promise(res => setTimeout(res, 1000)); - if I uncomment this it works
}
在这里,我看到console.log('pre', v)
被评估了4次,但console.log('post', v)
仅被评估了一次。如果我在for循环中取消注释睡眠,那么一切都会按预期进行。
答案 0 :(得分:1)
执行此操作时,这是一个同步发射,最终将发生一个事件,因为当发出源可观察对象时,switchMap将取消订阅/取消内部可观察对象,这在您的情况下是异步承诺。
它与以下情况类似
const e=new Subject();
e.pipe(switchMap(e=>timer(0).pipe(mapTo(e)))).subscribe(console.log)
for (let i = 0; i < 4; i++) {
e.next('updated');
}
您最终只会得到一个“更新”。这里的解决方案之一是将switchMap
替换为mergeMap
。
对于switchMap
来说,这确实是一种预期行为,其中获得的发射量取决于源发射频率与内部可观察发射的频率。