【问题标题】:Angular BehaviorSubject subscription fires only onceAngular BehaviorSubject 订阅只触发一次
【发布时间】:2020-03-15 14:46:21
【问题描述】:

我有一个 Angular 服务,它有一个名为 must_checkout 的布尔属性。我的服务还包含一个名为 observable_must_checkout 的属性,它是一个查看 must_checkout 的 BehaviorSubject。

然后,在我的组件中,我订阅了 observable_must_checkout

这有效,并且组件在第一次 must_checkout 更改时收到事件。然而,这只触发一次,随后对 must_checkout 的更改不起作用:

服务:

import { Injectable,  Input, Output } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

export class OrderingService
{

  must_checkout: boolean;
  observable_must_checkout = new BehaviorSubject<boolean>(this.must_checkout);

  constructor([...])
  {
    this.observable_must_checkout = new BehaviorSubject<boolean>(this.must_checkout);
  }

  ChangeSomething()
  {
    console.log("changing the value here...");
    this.must_checkout = true;
  }


}

父组件:

import { Component, OnInit } from '@angular/core';
import { OrderingService } from 'src/app/services/ordering.service';

@Component({
  selector: 'app-settle',
  templateUrl: './settle.component.html',
  styleUrls: ['./settle.component.css']
})

export class SettleComponent implements OnInit
{
  constructor(private OrderingService: OrderingService) { }

  ngOnInit()
  {
        this.basket = new OrderingService();
        this.basket.observable_must_checkout.subscribe((newValue: boolean) => { alert("value changed: " + newValue)  });

  }

  ngOnDestroy() {
    this.basket.observable_must_checkout.unsubscribe();
  }

}

【问题讨论】:

    标签: angular typescript rxjs observable


    【解决方案1】:

    我没有看到对 next() 的调用,这是您向 BehaviorSubject 的当前订阅者触发新事件的方式。您正在寻找类似的东西。

      ChangeSomething()
      {
        console.log("changing the value here...");
        this.observable_must_checkout.next(true); 
      }
    

    https://www.learnrxjs.io/subjects/

    另外,你不需要在构造函数中初始化主题,因为你在上面几行做了:

      observable_must_checkout = new BehaviorSubject<boolean>(this.must_checkout);
    
      constructor([...])
      {}
    

    【讨论】:

      【解决方案2】:

      你快到了。当您创建 BehaviorSubject 时,它使用值 must_checkout 作为其初始值,然后将其丢弃。这意味着对 must_checkout 的任何更改都将对您的 observable 产生影响。这等同于您正在做的事情。在此处复制并粘贴此代码,以查看 mustCheckOut 中的更改如何不会发出新信号。

      https://stackblitz.com/edit/rxjs-4jynuj?devtoolsheight=60

      import { of, BehaviorSubject } from 'rxjs'; 
      import { map } from 'rxjs/operators';
      
      
      let mustCheckOut:boolean = false;
      let obsMustCheckOut: BehaviorSubject<boolean> = new BehaviorSubject(mustCheckOut);
      
      
      obsMustCheckOut.asObservable().subscribe(signal => {
        console.log("I got a signal!", signal)
      })
      
      // This does not work. 
      // Even though you change the source `mustCheckout`, the BehaviorSubject does not listen to the change in this variable. You must ping a subject which can emit a signal to any subscribers. 
      setTimeout(() => {
        mustCheckOut = true
      }, 100)
      

      听起来您想在每次must_checkout 更改时发出一个新信号。您需要将您的 must_checkout 变量转换为可以发出信号的东西!那么订阅它的任何东西都会受到影响。

      import { of, BehaviorSubject,Subject, Observable } from 'rxjs'; 
      import { map, tap } from 'rxjs/operators';
      
      
      let mustCheckOut: Subject<boolean> = new Subject();
      let obsMustCheckOut: Observable<boolean> = mustCheckOut.asObservable().pipe(
        tap((signal) => console.log('I got the signal', signal)),
        // other manipulation or async requests can occur here.
      )
      
      
      obsMustCheckOut.subscribe(signal => {
        console.log("Here is the current signal!!!", signal)
      })
      
      
      setTimeout(() => {
        mustCheckOut.next(true)
      }, 100)
      
      setTimeout(() => {
        mustCheckOut.next(false)
      }, 2600)
      
      
      setTimeout(() => {
        mustCheckOut.next(true)
      }, 5500)
      

      我希望这对你有帮助。如果您需要更多说明,请告诉我。进一步阅读可以在这里找到:https://www.learnrxjs.io/subjects/behaviorsubject.html

      【讨论】:

        【解决方案3】:

        我遇到了同样的问题,但原因不同。

        这是我的声明。

          private clients: BehaviorSubject<ClientSummary[]> = new BehaviorSubject(undefined);
          public clients$: Observable<ClientSummary[]> = this.clients.asObservable();
        

        以及它是如何被消耗的

         this.clientService.clients$.subscribe(clients => {
            // do something with clients  
            console.log(clients);
         });
        
        

        当页面加载时,observable 触发了以下日志

        undefined
        

        但是,当在 BehaviorSubject 上调用 next 时,observable 没有再次触发。

          this.clients.next([/* some clients*/]);
        

        你能看出问题所在吗?

        这是非常微妙的,我花了一段时间才找到。

        解决方案

        更新初始值!

         private clients: BehaviorSubject<ClientSummary[]> = new BehaviorSubject([]);
        

        我不知道为什么,但是有了这个更改,每次下次调用 BehaviorSubject 时,observable 都不会更新。

        至于为什么我首先在​​那里有 undefined ? 应该是复制粘贴吧!

        【讨论】:

          猜你喜欢
          • 2019-09-22
          • 1970-01-01
          • 2021-04-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-18
          • 1970-01-01
          相关资源
          最近更新 更多