Есть ли в rxjs оператор логического типа?
У меня есть угловая служба, где я хочу раскрыть наблюдаемое, которое действует как своего рода логическое "или". Скажем, у меня есть несколько исходных последовательностей, которые могут дать on
а также off
ценности. Мне нужно вывести true
в любое время on
и вернитесь к false
когда все значения off
,
Пример:
const replaceInput = input => input === 'on' ? 'off' : 'on';
const getSource = (name) => Observable.interval(1000)
.scan(
input => Math.random() > 0.5 ? replaceInput(input) : input,
'off' // initial value
)
.do(val => console.log(`${name}: ${val});
const first$ = getSource('first');
const second$ = getSource('second');
const result$ = ???;
Теперь я попробовал с result$ = Observable.merge(first$, second$)
, но это дает всегда on
, Я также пытался с result$ = combineLatest(first$, second$)
, так что это несколько хорошо, но мои входы не синхронизированы, так что это не всегда идеально. Я имею в виду, что first$ может испускать более одного значения, в то время как second может никогда не сработать, и наоборот. Что еще я могу сделать?
Я думал о каком-то mergeMap или подобном, а затем сохранял состояние во внешнем контексте, чтобы я запускал обновления для любого события. Но затем я попадаю в проблему: событие "off" может означать "off", но только если другие последовательности также "off", поэтому это быстро становится сложным.
2 ответа
Вы на самом деле дали ответ в основном сами:
const result$ = Observable.combineLatest(first$, second$)
.map(values => values.some(value => value === 'on'));
так что это несколько хорошо, но мои входы не синхронизированы, так что это не всегда идеально.
Я не понимаю, что вы имеете в виду, если честно. Вы четко заявили в своем вопросе, что хотите этого:
Мне нужно выводить true каждый раз, когда что-то включено.
Поэтому, если входные данные изменяются с некоторой временной задержкой, у вас будет промежуточное состояние результата. Это совершенно соответствует вашему вопросу.
Если вы хотите подождать, пока все входные данные изменятся, потому что они могут измениться примерно в одно и то же время, вы можете добавить debounceTime
к нему:
const result$ = Observable.combineLatest(first$, second$)
.debounceTime(100)
.map(values => values.some(value => value === 'on'));
Или если вы хотите подавить false
Выбросы, просто отфильтруйте их:
const result$ = Observable.combineLatest(first$, second$)
.map(values => values.some(value => value === 'on'))
.filter(Boolean); // sneaky trick; you can also use "value => value"
Конечно, вы можете объединить оба.
Посмотреть, если это то, что вы ищете
let randomInput=()=>Rx.Observable.interval(1000)
.map(()=>Math.random()>0.5?'on':'off')
.startWith('off')
.map(value=>value==='on'?true:false)
Rx.Observable.combineLatest(randomInput(),randomInput())
.map(([first,second])=>first||second).subscribe(console.log)