Я использую оператор 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"]