我有点击事件流 - 让我们称之为流$。在事件处理程序中,我递增一个计数器(从0开始)并调用observer.next将counter作为参数传递。当计数器等于3时,我正在完成流。
让我们说我的Observable看起来像这样:
--a---b--c->
其中a,b和c是点击事件
现在,我正在采用所有先前的元素(计数器不等于3):
const a$ = stream$.pipe(filter(x => x !== 3))
最后一个元素(计数器等于3)
const b$ = stream$.pipe(filter(x => x === 3))
好的,让我们把它连接起来 - 带b $的$ $
const c$ = a$.pipe(concat(b$))
现在,订阅c$
c$.subscribe(console.log)
不幸的是,它不起作用。我只在控制台中获得1,2,但不是3(最后一个)。任何人都可以向我解释为什么会这样吗?
DEMO:https://stackblitz.com/edit/typescript-iucduj?file=index.ts
CODE:
let clickCounter = 0
const stream$ = Observable.create((observer) => {
document.addEventListener('click', () => {
clickCounter++;
observer.next(clickCounter)
if (clickCounter === 3) {
observer.complete()
}
})
})
const a$ = stream$.pipe(
filter(x => x !== 3)
)
const b$ = stream$.pipe(
filter(x => x === 3)
)
const c$ = a$.pipe(concat(b$))
c$.subscribe(console.log)
答案 0 :(得分:1)
在您的代码中,当您执行第二次过滤操作时,源将被清空,因此b $将无法获得任何内容。
按如下所示更改代码,使其按预期工作:
const stream2$ = stream$.shareReplay(3);
const a$ = stream2$.pipe(filter(x => x !== 3));
const b$ = stream2$.pipe(filter(x => x === 3));
const c$ = a$.pipe(concat(b$));
c$.subscribe(console.log);
答案 1 :(得分:1)
我认为有两件事需要注意:
您正在创建两个'click'
事件处理程序,因为您对$stream
进行了两次订阅。这意味着每次点击都会增加clickCounter
两次,这是我认为你不想要的。
concat
运算符仅在b$
完成后才订阅第二个Observable $a
。但是,当$a
完成时,值3
已经发送到b$
,但没有人在听。
所以我认为实现share()
的{{1}}用$stream
然后使用merge
代替concat
的最佳方式是因为b$
赢了&#因为filter
无论如何都会发出任何东西。
查看更新后的演示:https://stackblitz.com/edit/typescript-t3i7mj?file=index.ts
const stream$ = Observable.create(
(observer) => {
document.addEventListener('click', () => {
...
})
})
.pipe(
share()
);
...
const c$ = a$.pipe(merge(b$));
答案 2 :(得分:0)
除了您想要使用它的特定用途(我会听取关于官方http重播模式的评论),你会不会因为另一种方法而变得更好......例如:
var stream$ = Observable.fromEvent(document, 'click').pipe(
scan((acc:any, val:any) => [...acc,val], []),
take(3)
);
stream$.subscribe((x) => console.log('emits: ' + x))