RxJS - concat最后使用先前值

时间:2018-04-21 15:58:32

标签: javascript rxjs observable

我有点击事件流 - 让我们称之为流$。在事件处理程序中,我递增一个计数器(从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)

3 个答案:

答案 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)

我认为有两件事需要注意:

  1. 您正在创建两个'click'事件处理程序,因为您对$stream进行了两次订阅。这意味着每次点击都会增加clickCounter两次,这是我认为你不想要的。

  2. concat运算符仅在b$完成后才订阅第二个Observable $a。但是,当$a完成时,值3已经发送到b$,但没有人在听。

  3. 所以我认为实现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))