ZipWithLatestForm *需要操作员*或解决方法

ZipWithLatestForm *Wanted Operator* or Workaround

让我们考虑以下流:

Stream1: 1  2  3  4  5  6  7  8  9                
Stream2: abc  d       fg   h

我想通过组合这些流获得的输出:

[1, a]
[2, b]
[3, c]
[4, d]
[5, d]
[6, f]
[7, g]
[8, h]
[9, h]

示例代码思路: StackBlitz Editor Link

const input$ = fromEvent(document, 'keydown')
  .pipe(
    map((event: KeyboardEvent) => event.keyCode)
  );
const source$ = interval(500).pipe(s$ => zip(s$, input$))
source$.subscribe(x => console.log(x));

所以这类似于运算符 zip() and/or withLatestForm(),但我想不出解决方案

你可以只使用 withLatestFrom

import { of, fromEvent, interval } from 'rxjs'; 
import { map, withLatestFrom } from 'rxjs/operators';

const input$ = fromEvent(document, 'keydown').pipe( map((event: KeyboardEvent) => event.keyCode));
const timer$ = interval(1000);
const source$ = timer$.pipe(withLatestFrom(input$));

source$.subscribe(x => console.log(x));

在 stackblitz 试试这个现场演示 -> https://stackblitz.com/edit/rxjs-bmx7hg

一旦您聚焦页面并按下某个键,流就会开始,您将在每次滴答时获得一个发射值,无论您自上次滴答后是否单击了按钮。

我对 rxjs 的了解还不足以说明是否有一个内置函数已经这样做了,但是你应该能够使用显式队列来处理它:

import { of, fromEvent, interval } from 'rxjs'; 
import { map, withLatestFrom } from 'rxjs/operators';

const queue = [];
const input$ = fromEvent(document, 'keydown').pipe(map((event: KeyboardEvent) => {
    queue.push(event.keyCode);
    return queue;
});
const timer$ = interval(1000);
const source$ = timer$.pipe(withLatestFrom(input$), map(([tick, queue]) => {
    if (queue.length > 1)
        return queue.shift();
    else
        return queue[0];
}));

source$.subscribe(console.log);

经过一段时间的思考,我想出了这样的解决方案,StackBlitz Edit Link:

const interval$ = interval(500).pipe(share());
const input$ = fromEvent(document, 'keydown')
  .pipe(
    map((event: KeyboardEvent) => event.keyCode),
    concatMap(key => interval$.pipe(map(tick => key), take(1))),
  );

const source$ = interval$.pipe(withLatestFrom(input$))
source$.subscribe(x => console.log(x));

我在 interval$ 和 concatMap 的帮助下延迟了 input$(注意 take(1))。

ConcatMap 帮助我延长了 input$ 事件并等待间隔事件触发它自己的事件。使用 withLatestForm 帮助我将刻度与其自己的 input$ 值相匹配。