【问题标题】:combineLatest doesn't emit anything unless all inner observables have emitted at least 1 emissioncombineLatest 不会发射任何东西,除非所有内部 observables 都发射了至少 1 次发射
【发布时间】:2019-11-12 16:47:03
【问题描述】:

假设我有这 3 个 observables:

const numpad1$ = fromEvent(document, 'keydown')
.pipe(
    startWith(0),
    filter(({ key, code }) => key === '1' && code === 'Numpad1'),
    map(() => 1),
    scan((a, b) => a + b, 0),
);

const numpad2$ = fromEvent(document, 'keydown')
    .pipe(
        startWith(0),
        filter(({ key, code }) => key === '2' && code === 'Numpad2'),
        map(() => 1),
        scan((a, b) => a + b),
    );

const numpad3$ = fromEvent(document, 'keydown')
    .pipe(
        startWith(0),
        filter(({ key, code }) => key === '3' && code === 'Numpad3'),
        map(() => 1),
        scan((a, b) => a + b),
    );

然后我像这样使用combineLatest

combineLatest(numpad1$, numpad2$, numpad3$).subscribe(console.log)

在至少按一次小键盘 1、2 和 3 之前,订阅不会生成控制台日志。 每当任何内部 obersvables 发出时,我可以使用 rxjs 运算符来发出 observable 吗? 例如,在上面的示例中,我希望在第一次按下任何小键盘 1 时调用 console.log,而根本没有按下小键盘 2 和 3。所以结果应该是这样的:[1, 0, 0](0s,因为我使用的是startWith(0))。

【问题讨论】:

  • 所以你期望 RxJs 操作符在 Observable 没有发出时返回 0。或者换句话说 - 如果它不发射,则发射。没有这样的运算符。
  • 你在 startWith 的正确轨道上,但是你在之后过滤它,所以它什么都不做。
  • 将 startWith 移到每个流的末尾?

标签: rxjs


【解决方案1】:

解决方案实际上是将startWith(0) 移动到管道的末尾。 所以:

const numpad1$ = fromEvent(document, 'keydown')
    .pipe(
        filter(({ key, code }) => key === '1' && code === 'Numpad1'),
        map(() => 1),
        scan((a, b) => a + b, 0),
        startWith(0),
    );

【讨论】:

    【解决方案2】:

    startsWith 是被过滤器过滤掉的,这里我建议使用 map 函数。例如:

    const numpad3$ = fromEvent(document, 'keydown')
        .pipe(
            startWith(0),
            map(({ key, code }) => return key === '3' && code === 'Numpad3' ? 1 : 0)
        );
    

    如果满足条件则返回1,否则返回0。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      • 1970-01-01
      • 2020-01-12
      • 2022-01-24
      • 1970-01-01
      • 2017-08-10
      相关资源
      最近更新 更多