问题描述
我正在尝试使用在两个浏览器标签/窗口之间进行通信BroadcastChannel API .通讯似乎在两个角度服务实例之间进行,但未显示可观察值的更改.我正在尝试主要使用async
管道来实现这一目标.
我在 StackBlitz
上演示了我的问题我使用路由器显示了两个组件. (control
和display
)
我有一个服务(MessagingService
),其中有一个BehaviorSubject
和BroadcastChannel API
通讯.该服务被注入到两个组件中.
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>
绑定:<p>service value: {{ messenger.value$ | async }}</p>
注射:constructor(private messenger: MessagingService) { }
所以问题是,我在做什么错?我在display
中进行了其他订阅,并触发了next
调用,但异步绑定没有得到更新.我还在同一选项卡中看到了正确的MessageEvent
,并且数据中的值正确.
附加测试表明,当按下更改本地值的按钮时,该值已更新.因此,变更检测似乎是一个问题.
如果您要在角度上下文之外(即外部)对数据进行突变,那么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)
}
);
}
I'm trying to communicate between two browser tabs/windows using BroadcastChannel API. The communication seems to work between two instances of angular service, but changes to the values of the observable are not shown. I'm trying to achieve this using mainly the async
pipe.
I have a demo of my problem at StackBlitz
I have two component that are showed using the router. (control
and display
)
I have a service (MessagingService
) where I have a BehaviorSubject
and BroadcastChannel API
-communications. That service is injected into both components.
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;
}
When I open two tabs (one in /control
and one in /display
) I can increment the value in /control
and to receive the new values in /display
at console but the values wont be updated.
Binding: <p>service value: {{ messenger.value$ | async }}</p>
Injection: constructor(private messenger: MessagingService) { }
So the question is, what I'm doing wrong? I made additional subscription in display
and the fires the next
call but the async binding doesn't get updated. I'm also seeing the correct MessageEvent
in that same tab with correct value in data.
EDIT: Additional testing shows that the value is updated when the button for changing local value is pressed. So it seems to be an issue with change detection.
If you are mutating data outside of the angular context (i.e., externally), then angular will not know of the changes. You need to use ChangeDetectorRef
or NgZone
in your component for making angular aware of external changes and thereby triggering change detection.
In your case, Probably your service somehow breaks out of Angular's zone. That's why Angular is unable to detect Changes
This Should Work
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)
}
);
}
这篇关于角度:绑定到服务的可观察属性->值不更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!