Search code examples
javascriptrxjsrxjs-observables

How to create an observable that skips emissions between 2 events


The context is that of a musical piano. I am interested in catching key-up events that occur when the sustain pedal is not pressed.

I have these streams:

pedalDown$
pedalUp$
keyUp$

How can I pipe these together into an observable unsustainedUp$ that emits of keyUp$ events only while the pedal is not down?

I thought this could work, but unsustainedUp$ fires even when the keyUp$ comes after a pedalDown$ and before a pedalUp$.

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()

Solution

  • I think you could do it like this. Maybe you'll need startWith() depending on pedalUp$ functionality.
    Btw, are pedalDown$ and the others Subjects, BehaviorSubjects or ReplaySubjects?:

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

    Live demo: https://stackblitz.com/edit/rxjs-v2wkhq?devtoolsheight=60

    I tried also your solution because it looks to me like it should work as well and it does:

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

    So make sure when the source Observables emit because that might be the issue.