2017-02-03 12 views
6

У меня вопрос о многоадресных наблюдаемых и неожиданном (для меня) поведении, которое я заметил.Оператор с общим наблюдаемым и startWith

const a = Observable.fromEvent(someDom, 'click') 
    .map(e => 1) 
    .startWith(-1) 
    .share(); 

const b = a.pairwise(); 

a.subscribe(a => { 
    console.log(`Sub 1: ${a}`); 
}); 

a.subscribe(a => { 
    console.log(`Sub 2: ${a}`) 
}); 

b.subscribe(([prevA, curA]) => { 
    console.log(`Pairwise Sub: (${prevA}, ${curA})`); 
}); 

Таким образом, существует общий наблюдаемый a, который испускает 1 при каждом событии кликов. -1 испускается из-за оператора startWith. Наблюдаемый b просто создает новое наблюдаемое путем объединения последних двух значений из a.

Мои ожидания были:

[-1, 1] // first click 
[ 1, 1] // all other clicks 

Что я заметил, был:

[1, 1] // from second click on, and all other clicks 

То, что я заметил, что значение -1 испускается непосредственно и потребляются Sub 1, прежде чем даже Sub 2 подписанный на наблюдаемый, и поскольку a является многоадресной, Sub 2 опоздает для участника.

Теперь я знаю, что могу многоадресную рассылку через BehaviourSubject и не использовать оператор startWith, но я хочу понять пример использования этого сценария, когда я использую startWith и multicast через share.

Насколько я понимаю, всякий раз, когда я использую .share() и .startWith (x), только один абонент будет уведомлен о значении startWith, поскольку все остальные подписчики подписываются после испускания значения.

Так что это причина для многоадресной передачи через какой-либо специальный объект (Behavior/Replay ...) или мне что-то не хватает в этом сценарии startWith/share?

Спасибо!

+0

Я столкнулся с той же проблемой. Можете ли вы привести пример с BehaviourSubject? – Eselfar

ответ

7

Это на самом деле правильное поведение.

.startWith() излучает свое значение каждому новому абоненту, а не только первому. Причина, по которой b.subscribe(([prevA, curA]) так и не получила, заключается в том, что вы используете многоадресную рассылку с .share() (aka .publish().refCount()).

Это значит, что первый a.subscribe(...) делает .refCount(), чтобы подписаться на него, он останется в подписке (обратите внимание, что Observable .fromEvent(someDom, 'click') не завершен).

Затем, когда вы, наконец, назвать b.subscribe(...) это будет подписываться только Subject внутри .share() и никогда не будет проходить через .startWith(-1), потому что это и уже многоадресной подписался в .share().

+0

Эй! Это было также тем, что я понял, большое спасибо за подробное объяснение того, почему наблюдение имеет смысл. Одним из решений этого сценария является также использование подключаемых наблюдаемых и вызов соединения после настройки подписки. Таким образом, все подписчики получат значение startWith. – dinony

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

  • Нет связанных вопросов^_^