【问题标题】:Communication between multiple components with a service by using Observable and Subject in Angular 2使用 Angular 2 中的 Observable 和 Subject 实现多个组件与服务之间的通信
【发布时间】:2017-10-31 08:00:54
【问题描述】:

我是 rxjs 新手,所以想问一个关于 Angular 2ObservablesBehaviorSubject/Subject 的问题。

所以,我想要实现的是:button 中的onclick ComponentA 以通知其他组件,例如ComponentBComponentC

到目前为止我所做的是创建一个service

private isMenuOpenBS = new BehaviorSubject(false);

  toggleMenu(): void {
    this.isMenuOpenBS.next(!this.isMenuOpenBS.getValue());
  }

  getMenuState(): Observable<boolean> {
    return this.isMenuOpenBS.asObservable();
  }

然后拥有一个带有provide menuService 的组件正在调用this.menuService.toggleMenu(),这会改变BehaviorSubject 的值。代码:

toggleMenu(): void {
    this.menuService.toggleMenu();
    this.menuService.isMenuOpenBS.subscribe(
      (data) => {
        console.log(data)
      },
      (e) => {console.log(e)},
      () => {console.log('completed')}
    )
  }

还有另一个组件,OnInit() subscribesgetMenuState(),这是一个 Observable,但它仅在 OnInit() 上获取值。代码:

ngOnInit(): void {
    this.menuService.getMenuState().subscribe(
      (data)=>{
        this.messages = data;
        console.log('nav component');
      },
      (e) => {console.log(e)},
      () => {console.log('completed')}
    )
  }

complete 函数永远不会被调用。

任何想法我做错了什么或者我在逻辑中遗漏了什么?

--

编辑:所以,为了解释更多问题,我可以看到 observable 具有 oninit 的第一个值,但没有别的。之后没有错误没有完成,或者没有“下一个”值,这是错误的,因为我从主题发送了新值。最终问题出在组件的提供者列表上,而不是 observables 或 subject 的问题,但在解决问题之前,很难看出问题所在。

【问题讨论】:

  • 你在哪里“完成” observable?
  • 无处可去。那是缺少的吗?在我看来,我在想我不想complete 它,所以它可以一直获得价值。或者我每次获取值时都必须complete它,这样它才能在另一个组件调用toggle方法之后获取新的值?
  • 这就是你所缺少的。如果你完成了这个主题,observable 就会死掉。
  • 所以我必须在某个地方打电话给complete()?对不起,我有点困惑,是否可以在代码中写下我应该在哪里做?基本上,我有 1 个shared service 和 2 个components
  • 为什么要完成observable?如果这样做,您将无法 next

标签: angular observable angular2-services angular2-observables behaviorsubject


【解决方案1】:

您可以通过子父关系或通过服务在组件之间进行通信。

https://angular.io/docs/ts/latest/cookbook/component-communication.html

但是有一种方法可以通过ngrx/store。这个概念类似于 Redux。你可以试试看。

【讨论】:

  • 谢谢,但我不想交流亲子或子父母。而不是一个服务持有状态并将其共享给多个组件而不引入另一个库。不过谢谢你的回答。这个jasonwatmore.com/post/2016/12/01/… 帮助我意识到providers 数组的问题。
【解决方案2】:

我粘贴的代码没有有问题。 我的问题是我创建的 2 components 在他们的 providers 数组中注入了“MenuService”,所以我没有单例。

我从两个组件的providers 数组中删除了该服务,它起作用了!

PS:这个http://jasonwatmore.com/post/2016/12/01/angular-2-communicating-between-components-with-observable-subject 是一个有用的教程,可以帮助我解决providers 数组的问题。

【讨论】:

    【解决方案3】:

    一些事情......

    1. 您无需将 BehaviorSubject 作为可观察对象返回,您应该能够订阅可观察对象,没有问题。
    2. 您不应该在每次调用切换功能时都继续订阅服务。通过这样做,您将创建大量订阅。如果您采纳了我上面的建议,您只需记录 getValue() 函数的返回即可。

    很高兴你解决了它!

    【讨论】:

    • 嗨@MichaelSolati。关于您的第一条评论,我相信您会更频繁地返回可观察对象而不是主题/行为主题以实现不变性。这样任何组件都不会改变状态——只得到它。关于第二条评论,您能否详细说明创建了多少订阅?据我了解,唯一存在的订阅是组件将.subscribe 的订阅。代码中的 console.log() 仅用于 PoC。
    • 这有点像setInterval() 函数,您可以在其中重复调用该函数。每个实例都是订阅的单独出现。因为它没有附加到组件中的变量,所以您永远不会结束订阅/unsubscribe()(每次调用 toggleMenu() 时都会初始化一个新订阅)。
    • 好吧,我明白你的意思了。是的,它应该类似于:this.subscription = this.menuService.getMenuState().subscribe( (data) =&gt; { this.menuState = data; }, (e) =&gt; { console.log(e); }, () =&gt; {console.log('completed'); }); private subscription: Subscription。但是,正如我之前所说,console.log 是针对 PoC 的。不过感谢 cmets!
    猜你喜欢
    • 1970-01-01
    • 2018-10-13
    • 2019-10-10
    • 1970-01-01
    • 2020-02-05
    • 2019-12-31
    • 2017-10-18
    • 2019-03-24
    • 1970-01-01
    相关资源
    最近更新 更多