2015-09-27 5 views
5

Я пытаюсь изучить библиотеку RxJS. Один из случаев, которые я не совсем понимаю, описан в this jsfiddle (код также ниже).RxJS combinationLatest: как получить emit после изменения только одного значения?

var A= new Rx.Subject(); 
var B= new Rx.Subject(); 

A.onNext(0);  

// '.combineLatest' needs all the dependency Observables to get emitted, before its combined signal is emitted. 
// 
// How to have a combined signal emitted when any of the dependencies change (using earlier given values for the rest)? 
//  
A.combineLatest(B, function (a,b) { return a+b; }) 
.subscribe(function (v) { console.log("AB: "+ v); }); 

B.onNext("a"); 
A.onNext(1); 

Я хотел бы получить два испускания в журнал «AB». Один из изменений B в «a» (A уже имеет значение 0). Другое от изменения A до 1.

Однако изменения, которые возникают после подписки, по-видимому, имеют значение (даже если A имеет значение и, следовательно, объединенный результат может быть вычислен).

Должен ли я использовать «горячие наблюдаемые» для этого или какой-либо другой метод, кроме .combineLatest?

Моя проблема в фактическом коде (больше, чем этот образец) заключается в том, что после подписки мне нужно сделать отдельные инициализации, которая сокращает материал в двух отдельных местах, вместо того, чтобы четко определять начальные значения.

Благодаря

ответ

9

Я думаю, вы не поняли, как работает Subjects работу. Subjects hot Observables. Они не держатся за ценности, поэтому, если они получат onNext без подписчиков, это значение будет потеряно для всего мира.

Что вы ищете - это либо BehaviorSubject, либо ReplaySubject, оба из которых имеют прошлые значения, которые переизлучают их новым подписчикам. В первом случае вы всегда построить его с начальным значением

//All subscribers will receive 0 
var subject = new Rx.BehaviorSubject(0); 

//All subscribers will receive 1 
//Including all future subscribers 
subject.onNext(1); 

в последнем вы установите количество значений, которые можно воспроизвести для каждой подписки

var subject = new Rx.ReplaySubject(1); 
//All new subscribers will receive 0 until the subject receives its 
//next onNext call 
subject.onNext(0); 

Переписывая ваш пример это может быть:

var A= new Rx.BehaviorSubject(0); 
var B= new Rx.Subject();  

// '.combineLatest' needs all the dependency Observables to get emitted, before its combined signal is emitted. 
// 
// How to have a combined signal emitted when any of the dependencies change (using earlier given values for the rest)? 
//  
A.combineLatest(B, function (a,b) { return a+b; }) 
.subscribe(function (v) { console.log("AB: "+ v); }); 

B.onNext("a"); 
A.onNext(1); 

//AB: 0a 
//AB: 1a 

На другой ноте, понимая, конечно, что это все для вас новичок, в большинстве случаев вам не нужно использовать Subject напрямую, так как обычно это mea что вы пытаетесь прервать Rx в безопасности ваших известных парадигм. Вы должны спросить себя, откуда берутся ваши данные? Как он создается? Если вы зададите эти вопросы достаточно, следуя цепочке событий, возвращающейся к источнику, 9 из 10 раз вы обнаружите, что для него, вероятно, есть обертка Observable.

+0

Очень хороший ответ Пол, спасибо! BehaviorSubject действительно работает для меня, и я очень ценю последний абзац, который вы написали. Держу пари, что ты прав. Мои значения - от перетаскивания мышью; пойдет дальше с документацией Rx, чтобы понять ее более полно. – akauppi

+1

@akauppi yep mouse drags - это, конечно, наблюдаемые события, проверьте [fromEvent] (https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/fromevent.md). В полноте времени, когда у вас больше опыта работы с Rx, вы можете узнать, как связать все это вместе с источником наблюдаемых событий мыши вплоть до вашего окончательного наблюдаемого результата, используя только операторы Rx, без необходимости работать непосредственно с 'Subjects '. – Brandon

+0

@Brandon Я изучаю Rx прямо сейчас. :) В конечном итоге опубликует мой эксперимент, объединяющий SVG с RxJs (думаю, связывая объекты вместе). – akauppi

Смежные вопросы