Я использую оператор withLatestFrom
в RxJS обычным способом:
var combined = source1.withLatestFrom(source2, source3);
... активно собирать самую последнюю эмиссию от source2
и source3
и излучать все три значения только тогда, когда испускает source1
.
Но я не могу гарантировать, что source2
или source3
будут выдавать значения до того, как source1
выдает значение. Вместо этого мне нужно подождать, пока все три источника не произведут хотя бы одно значение, прежде чем позволить withLatestFrom
выполнить свою задачу.
Контракт должен быть: если source1
испускает, то combined
будет всегда в конечном итоге испускаться, когда в конечном итоге будут получены другие источники. Если source1
излучает несколько раз, ожидая других источников, мы можем использовать последнее значение и отменить предыдущие значения. Изменить: как мраморную диаграмму:
--1------------2---- (source)
----a-----b--------- (other1)
------x-----y------- (other2)
------1ax------2by--
--1------------2---- (source)
------a---b--------- (other1)
--x---------y------- (other2)
------1ax------2by--
------1--------2---- (source)
----a-----b--------- (other1)
--x---------y------- (other2)
------1ax------2by--
Я могу создать для этого пользовательский оператор, но я хочу убедиться, что я не пропустил очевидный способ сделать это с помощью ванильных операторов. Это похоже на то, что я хочу combineLatest
для исходного испускания, а затем перейти к withLatestFrom
с этого момента, но я не смог понять, как это сделать.
Изменить: Полный пример кода из окончательного решения:
var Dispatcher = new Rx.Subject();
var source1 = Dispatcher.filter(x => x === 'foo');
var source2 = Dispatcher.filter(x => x === 'bar');
var source3 = Dispatcher.filter(x => x === 'baz');
var combined = source1.publish(function(s1) {
return source2.publish(function(s2) {
return source3.publish(function(s3) {
var cL = s1.combineLatest(s2, s3).take(1).do(() => console.log('cL'));
var wLF = s1.skip(1).withLatestFrom(s2, s3).do(() => console.log('wLF'));
return Rx.Observable.merge(cL, wLF);
});
});
});
var sub1 = combined.subscribe(x => console.log('x', x));
// These can arrive in any order
// and we can get multiple values from any one.
Dispatcher.onNext('foo');
Dispatcher.onNext('bar');
Dispatcher.onNext('foo');
Dispatcher.onNext('baz');
// combineLatest triggers once we have all values.
// cL
// x ["foo", "bar", "baz"]
// withLatestFrom takes over from there.
Dispatcher.onNext('foo');
Dispatcher.onNext('bar');
Dispatcher.onNext('foo');
// wLF
// x ["foo", "bar", "baz"]
// wLF
// x ["foo", "bar", "baz"]