Angular: привязка к наблюдаемому свойству сервиса -> значение не обновляется
Я пытаюсь установить связь между двумя вкладками / окнами браузера с помощью BroadcastChannel API. Связь, кажется, работает между двумя случаями углового обслуживания, но изменения значений наблюдаемого не показаны. Я пытаюсь добиться этого, используя в основном async
труба.
У меня есть демо моей проблемы на StackBlitz
У меня есть два компонента, которые показаны с помощью маршрутизатора. (control
а также display
)
У меня есть сервис (MessagingService
) где у меня есть BehaviorSubject
а также BroadcastChannel API
-communications. Этот сервис внедряется в оба компонента.
export class MessagingService {
private _value = 1;
valueSubject: BehaviorSubject<number> = new BehaviorSubject<number>(this._value);
value$: Observable<number> = this.valueSubject.asObservable();
private bc: BroadcastChannel = new BroadcastChannel('controlChannel');
constructor() {
this.bc.onmessage = this.handleEvent;
}
Когда я открываю две вкладки (одна в /control
и один в /display
) Я могу увеличить значение в /control
и получить новые значения в /display
на консоли, но значения не будут обновлены.
Переплет: <p>service value: {{ messenger.value$ | async }}</p>
Раствор для инъекций: constructor(private messenger: MessagingService) { }
Итак, вопрос в том, что я делаю не так? Я сделал дополнительную подписку в display
и пожары next
вызов, но асинхронная привязка не обновляется. Я также вижу правильный MessageEvent
в той же вкладке с правильным значением в данных.
РЕДАКТИРОВАТЬ: дополнительное тестирование показывает, что значение обновляется при нажатии кнопки для изменения локального значения. Так что, похоже, проблема с обнаружением изменений.
1 ответ
Если вы изменяете данные вне углового контекста (то есть извне), то angular не будет знать об изменениях. Вам нужно использовать ChangeDetectorRef
или же NgZone
в вашем компоненте для информирования о внешних изменениях под углом и, таким образом, запускает обнаружение изменений.
В вашем случае, вероятно, ваш сервис каким-то образом выйдет из зоны Angular. Вот почему Angular не может обнаружить изменения
Это должно работать
import { Component, OnInit, OnDestroy, NgZone } from '@angular/core';
@Component({
selector: 'app-display',
template:
//.....rest of the code
constructor(private messenger: MessagingService,private zone: NgZone,) {}
ngOnInit() {
this.data = new Data();
this.sub = this.messenger.value$.subscribe(
res => {
this.zone.run(() => this.data.value = res)
}
);
}
ZONES IN ANGULAR
UNDERSTANDING ZONES
ANGULAR CHANGE DETECTION EXPLAINED
Forked StackBlitz