3

我正在尝试使用BroadcastChannel API在两个浏览器选项卡/窗口之间进行通信。通信似乎在两个角度服务实例之间工作,但未显示对可观察值的更改。我正在尝试主要使用async管道来实现这一目标。

我在StackBlitz上演示了我的问题

我有两个使用路由器显示的组件。(controldisplay)

我有一个服务 ( MessagingService),我有一个BehaviorSubjectBroadcastChannel 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;
  }

当我打开两个选项卡(一个 in/control和一个 in /display)时,我可以增加 in的值并在控制台/control中接收新值,/display但不会更新这些值。

捆绑:<p>service value: {{ messenger.value$ | async }}</p>

注射:constructor(private messenger: MessagingService) { }

所以问题是,我做错了什么?我进行了额外的订阅display并触发了next调用,但异步绑定没有得到更新。我还在MessageEvent同一个选项卡中看到正确的数据值正确。

编辑:附加测试表明,当按下更改本地值的按钮时,值会更新。所以这似乎是变更检测的问题。

4

1 回答 1

1

如果您在角度上下文之外(即外部)改变数据,那么角度将不知道这些变化。您需要在您的组件中使用ChangeDetectorReforNgZone来从角度感知外部变化,从而触发变化检测。

在您的情况下,您的服务可能会以某种方式突破 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)
      }
    );
  }
  1. ZONES IN ANGULAR
  2. UNDERSTANDING ZONES
  3. ANGULAR CHANGE DETECTION EXPLAINED

Forked StackBlitz

于 2018-07-10T18:32:21.483 回答