如何创建一个跳过两个事件之间的发射的可观察对象

How to create an observable that skips emissions between 2 events

上下文是一架音乐钢琴。我有兴趣捕捉 key-up 发生的事件 当延音踏板未被按下时 .

我有这些流:

pedalDown$
pedalUp$
keyUp$

我如何将它们组合到一个可观察的 unsustainedUp$ 中,仅当踏板未踩下时才发出 keyUp$ 事件?

我认为这可行,但即使 keyUp$pedalDown$ 之后和 pedalUp$ 之前,unsustainedUp$ 也会触发。

unsustainedUp$ = keyUp$.pipe(
    skipUntil(pedalUp$),
    takeUntil(pedalDown$),
    repeat()
)

// once at setup, fire into pedal-up to get this into the correct, normal piano initial state
pedalUp$.next()

我想你可以这样做。根据 pedalUp$ 功能,您可能需要 startWith()
顺便说一句,pedalDown$ 和其他 SubjectsBehaviorSubjectsReplaySubjects?:

pedalUp$.pipe(
  switchMap(() => keyUp$.pipe(
    takeUntil(pedalDown$),
  )),

现场演示:https://stackblitz.com/edit/rxjs-v2wkhq?devtoolsheight=60

我也尝试了您的解决方案,因为在我看来它应该也能正常工作,而且确实如此:

https://stackblitz.com/edit/rxjs-ngorgw?devtoolsheight=60

因此请确保源 Observables 何时发出,因为这可能是问题所在。

您的流设置使这有点困难。一种方法是对踏板当前是否在其自己的流中向上进行编码,当踏板向上时发出 true,当踏板向下时发出 false。这里我默认了true(踏板启动)。

然后我们可以将两者结合起来,在踩下踏板时过滤掉所有值,然后在适当的时候发出 keyUp$ 值。

像这样:

const isPedalUp$ = merge(
  pedalUp$.pipe(mapTo(true)),
  pedalDown$.pipe(mapTo(false))
).pipe(
  startWith(true)
);

unsustainedUp$ = keyUp$.pipe(
  withLatestFrom(isPedalUp$),
  filter(([_,isUp]) => isUp),
  map(([kepUp,_]) => kepUp)
);

另一种方法是切换进出 keyUp$。如果还没有,您需要多播 keyUp$

unsustainedUp$ = merge(
  pedalUp$.pipe(mapTo(true)),
  pedalDown$.pipe(mapTo(false))
).pipe(
  startWith(true),
  switchMap(isUp => isUp ?
    keyUp$,
    EMPTY
  )
);