角度:绑定到服务的可观察属性->值不更新 [英] Angular: Binding to a observable property of service -> value doesn't update

查看:92
本文介绍了角度:绑定到服务的可观察属性->值不更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用在两个浏览器标签/窗口之间进行通信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;
  }

当我打开两个选项卡时(在/control中一个,在/display中一个),我可以增加/control中的值,并在控制台上通过/display接收新值,但是这些值不会被更新./p>

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

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

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

附加测试表明,当按下更改本地值的按钮时,该值已更新.因此,变更检测似乎是一个问题.

解决方案

如果您要在角度上下文之外(即外部)对数据进行突变,那么angular将不会知道这些变化.您需要在组件中使用ChangeDetectorRefNgZone,以使角度感知外部变化,从而触发变化检测.

在您的情况下,您的服务可能会以某种方式脱离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

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. (controland 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 displayand 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)
      }
    );
  }

  1. ZONES IN ANGULAR
  2. UNDERSTANDING ZONES
  3. ANGULAR CHANGE DETECTION EXPLAINED

Forked StackBlitz

这篇关于角度:绑定到服务的可观察属性->值不更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆