Angular BehaviorSubject订阅仅触发一次

时间:2019-11-20 00:35:42

标签: angular typescript rxjs observable

我有一个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();
  }

}

3 个答案:

答案 0 :(得分:3)

我没有看到对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([...])
  {}

答案 1 :(得分:2)

您快到了。创建BehaviorSubject时,它将使用值must_checkout作为其初始值,然后将其丢弃。这意味着对must_checkout所做的任何更改都会对您的可观察物产生影响。这等于您在做什么。在此处复制并粘贴此代码,以查看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

答案 2 :(得分:0)

我有同样的问题,但原因不同。

这是我的声明。

  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);
 });

页面加载后,可观察对象触发了以下日志

undefined

但是,在BehaviorSubject上调用next时,可观察对象不再触发。

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

您能看到问题吗?

这很微妙,花了我一段时间才能找到答案。

解决方案

更新初始值!

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

我不知道为什么,但是通过此更改,每次在BehaviorSubject上调用下一次时,可观察到的不更新。

至于为什么我首先在​​那里没有定义? 大概复制并粘贴!