shareReplay vs ReplaySubject - только ReplaySubject кэширует последнее значение перед подпиской - PullRequest
0 голосов
/ 04 января 2019

У меня есть внешний горячий источник, передающий значения, прежде чем наблюдатели смогут подписаться. После подписки, опоздавшие наблюдатели должны получить последнее значение и каждое значение с этого момента. Для этого я использовал следующий код (соответствующая строка помечена '<<<', <code>s Subject здесь только для того, чтобы можно было создать простейший из возможных примеров, в действительности горячий источник работает по-другому):

// irrelevant, just to send values
const s = new Subject();

// make the observable cache the last value
const o = s.pipe(shareReplay(1)); // <<<

// now, before subscription, values start coming in
s.next(1);
s.next(2);
s.next(3);

o.subscribe(n => console.warn('!!!', n));

Это не работает (я ожидал, что он напечатает !!! 3, но ничего не происходит), но я нашел способ заставить его работать:

// irrelevant, just to send values
const s = new Subject();

const r = new ReplaySubject(1);
s.subscribe(r);
const o = r.asObservable();

s.next(1);
s.next(2);
s.next(3);

o.subscribe(n => console.warn('!!!', n));

т.е. вместо использования shareReplay(1), я создаю ReplaySubject(1) и использую его как мост. С этим кодом я получаю желанный !!! 3.

Хотя я счастлив, что это работает, я хотел бы понять, почему первый фрагмент не работает. Я всегда думал, что shareReplay в значительной степени эквивалентен второму способу и фактически реализован таким образом. Чего мне не хватает?

1 Ответ

0 голосов
/ 07 января 2019

Когда вы используете s.pipe(shareReplay(1)), вы просто добавляете оператор в цепочку (например, меняете прототип цепочки). Но подписки нет, и shareReplay не подписывается на свой источник, когда у него нет наблюдателей. Так что он ничего не кэширует, потому что нет подписки на источник Observable, даже если источник «горячий».

Однако, когда вы используете s.subscribe(r), вы регулярно подписываетесь на s, поэтому r начинает получать элементы и ReplaySubject будет их кэшировать.

...