Я пытаюсь понять, как работает publishReplay
в rx js. У меня есть пример, в котором он работает должным образом:
const source = new Subject()
const sourceWrapper = source.pipe(
publishReplay(1),
refCount()
)
const subscribeTest1 = sourceWrapper
.subscribe(
(data: any) => {
console.log('subscriber1 received a value:', data)
}
)
source.next(1)
source.next(2)
setTimeout(() => {
const subscribeTest2 = sourceWrapper
.subscribe(
(data: any) => {
console.log('subscriber2 received a value:', data)
}
)
}, 5000)
У нас есть тема и обертка, в которую добавлены publushReplay(1), refCount()
. Мы создаем первую подписку, а затем выдаем 2 значения. В результате мы видим в консоли следующее:
subscriber1 received a value: 1
subscriber1 received a value: 2
И через 5 секунд создаем еще одну подписку, которая получает последнее буферизованное значение из ReplaySubject
, созданного publishReplay(1)
. В результате через 5 секунд мы увидим еще одну заметку в консоли:
subscriber2 received a value: 2
Ссылка на stackblitz
Пока все хорошо.
Но у меня есть другой пример, где я пытаюсь применить этот шаблон в приложении Angular. Вот ссылка .
Он содержит один модуль с 2 компонентами app.component.ts
и hello.component.ts
и 1 сервис test.service.ts
test.service .ts
@Injectable({
providedIn: 'root'
})
export class TestService {
private _test$: Subject<string> = new Subject()
public get test$(): Observable<string> {
return this._test$.pipe(
publishReplay(1),
refCount()
)
}
public pushToStream(val: string): void {
this._test$.next(val)
}
}
app.component.ts
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
public name = 'Angular';
constructor(private testService: TestService) {}
public ngOnInit(): void {
this.testService.test$.subscribe((data: string) => {
console.log('Subscriber in app.component received a value: ', data)
})
this.testService.pushToStream('new value')
this.testService.pushToStream('one more value')
}
}
app.component. html
<hello name="{{ name }}"></hello>
<p>
Start editing to see some magic happen :)
</p>
hello.component.ts
@Component({
selector: 'hello',
template: `<h1>Hello {{name}}!</h1>`,
styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent implements OnInit {
@Input() name: string;
constructor(private testService: TestService) { }
public ngOnInit(): void {
setTimeout(() => {
this.testService.test$.subscribe((data: string) => {
console.log('Subscriber in hello component received a value:', data)
})
}, 4000)
}
}
Здесь тот же принцип: удерживайте источник в службе, который является синглтоном, создайте 1 подписку в app.component.ts
, выдать 2 значения и создать еще одну подписку с задержкой в hello.component.ts
. Как мы могли видеть в предыдущем примере, вторая подписка должна получить последнее буферизованное значение, но это не так. В консоли мы видим только следующее:
Subscriber in app.component received a value: new value
Subscriber in app.component received a value: one more value
Что мне не хватает и почему это не работает?