#javascript #rxjs #rxjs-observables
#javascript #rxjs #rxjs-наблюдаемые
Вопрос:
Контекст — это контекст музыкального пианино. Я заинтересован в улавливании событий нажатия клавиш, которые происходят, когда педаль сустейна не нажата.
У меня есть эти потоки:
pedalDown$
pedalUp$
keyUp$
Как я могу объединить их вместе в наблюдаемый объект, который выдает события только тогда, когда педаль не нажата? unsustainedUp$
keyUp$
Я думал, что это может сработать, но unsustainedUp$
срабатывает даже тогда, когда keyUp$
после a pedalDown$
и перед 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()
Ответ №1:
Я думаю, вы могли бы сделать это так. Возможно, вам понадобится startWith()
в зависимости от pedalUp$
функциональности.
Кстати, are pedalDown$
и другие Subjects
, BehaviorSubjects
или ReplaySubjects
?:
pedalUp$.pipe(
switchMap(() => keyUp$.pipe(
takeUntil(pedalDown$),
)),
Живая демонстрация: https://stackblitz.com/edit/rxjs-v2wkhq ?devtoolsheight=60
Я попробовал также ваше решение, потому что мне кажется, что оно должно работать так же хорошо, и оно работает:
https://stackblitz.com/edit/rxjs-ngorgw?devtoolsheight=60
Поэтому убедитесь, что исходные наблюдаемые объекты излучают, потому что это может быть проблемой.
Ответ №2:
Настройка ваших потоков делает это несколько сложнее. Один из способов сделать это — закодировать, включена ли педаль в данный момент в свой собственный поток, который выдает 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
)
);