【问题标题】:Reactivo Programming ExerciseReactivo 编程练习
【发布时间】:2019-07-15 03:43:41
【问题描述】:

我有一个可观察的源,当您单击时会发出。我想制作一个像下一个大理石图一样发出的运算符...

也就是说,它在第一次点击时发出。然后,当你有 2 个项目时它会发射,然后当你有 3 个项目时它会发射,等等。

我知道可以使用扫描和过滤运算符来完成,但我的问题是,是否可以使用 bufferWhen 运算符来做到这一点?

我尝试这样做(如this),但结果不是我所期望的(第一次点击不会立即发出)。

【问题讨论】:

    标签: rxjs reactive-programming


    【解决方案1】:

    它的工作原理如下代码。尽量避免在bufferWhen 中重复使用源代码,可能存在竞争条件

    const source$ = fromEvent(document, 'click').pipe(
      map(_ => new Date())
    );
    
    interval(1000).pipe(
      tap(d => console.log('CLICK:', d)),
      bufferWhen(() => {
        return source$
      })
    ).subscribe(console.log);
    

    【讨论】:

    • 问题在于源 observable 也是点击事件。因此,由于竞争条件,无法使用 bufferWhen 运算符来执行此操作
    • 结合使用 reduce() 和 repeat() 可能更有意义。 bufferWhen 它通常应该由第三方 observable 控制
    【解决方案2】:

    我找到了使用groupBy 运算符的解决方案。

    Stackblitz 中的演示。

    代码如下:

    function emitSequentially<T>(source$: Observable<T>) {
        return defer(() => {
            let emitWhen = 1;
            return source$.pipe(
                groupBy(_ => emitWhen),
                mergeMap(group$ =>
                    group$.pipe(
                        take(emitWhen),
                        toArray(),
                        tap(_ => ++emitWhen)
                    )
                )
            );
        });
    }
    
    const source1$ = fromEvent(document, 'click').pipe(
        scan<Event, number>(acc => ++acc, 0)
    );
    const source2$ = interval(500).pipe(
        scan(acc => ++acc, 0)
    );
    
    emitSequentially(source1$).subscribe(x => console.log('Emitting from click: ', x));
    setTimeout(() => {
        emitSequentially(source2$).subscribe(x => console.log('Emitting from interval: ', x));
    }, 1000);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-27
      • 1970-01-01
      • 2017-12-20
      • 1970-01-01
      • 2015-01-14
      • 1970-01-01
      • 1970-01-01
      • 2011-11-01
      相关资源
      最近更新 更多