Angular 9: Observable Getter 从 BehaviorSubject 返回对象而不是布尔值

Angular 9: Observable Getter Returning Object Instead of Boolean from BehaviorSubject

如果这篇文章发布在 Stack Overflow 的某处,我深表歉意,但我找不到适合我的答案。

我有一个 BehaviorSubject 以布尔值形式跟踪状态。我还有一个 public getter 方法,它是一个 return 是 BehaviorSubject 的 Observable。我这样做是为了不仅可以订阅 BehaviorSubject 值的更改,还可以在它没有更改时获取当前值。虽然我能够从订阅中获得正确的值,但我在调用 getter 时得到了一个对象 returned。我想要它 return 最后一个值。

我试过使用 .getValue(),它似乎不起作用,我也试过 .value,它似乎有效但在 IDE.

我创建了一个非常基本的示例来说明我要完成的任务,并且我在 my.service.ts 文件中添加了注释以说明我的目标。请指教。谢谢!

编辑:我默认使用堆栈闪电战中的内容,并将 getter 分配给 name 变量只是为了查看它。我的目标是获得价值,以便我可以根据价值是真还是假来做一些事情。我确定我错过了一些非常简单的东西。

编辑:按要求向问题添加代码

编辑:我还添加了 .subscribe 以表明虽然我理解 Observables 是如何工作的,但我还想使用相同的 [=40= 检查值更改的值 OUTSIDE ] 如果可以的话。

我的服务

import { Observable, BehaviorSubject } from "rxjs";

export class MyService {

  constructor() {}

  private _isBoolean = new BehaviorSubject<boolean>(false);

  public get isBoolean(): Observable<boolean> {
    //return this._isBoolean.value; // Returns boolean, but throws error "Type 'boolean' is not assignable to type 'Observable<boolean>'."
    return this._isBoolean; // Returns object, but I want the value
  }

}

AppComponent

import { Component } from '@angular/core';
import { MyService } from './my.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name;

  constructor(private _myservice: MyService) {
    this._myservice.isBoolean.subscribe(val => {
      console.log("value from subscribe: " + val)
    })

    this.name = this._myservice.isBoolean;
    if (this._myservice.isBoolean) {
      console.log("true!");
    } else if (!this._myservice.isBoolean) {
      console.log("false!");
    }
  }
}

https://stackblitz.com/edit/angular-hhdgrc

问题出在应用程序的 html 部分,服务 returns 模板必须订阅的可观察对象。为此,您必须将异步管道添加到模板变量

将异步管道添加到应用 component.html 变量。这样就可以了

<hello name="{{ name|async }}"></hello>

您使用 Observables 的方式有误。请添加一个 subscribe 调用到 observable:

this._myservice.isBoolean.subscribe((val) => {
    this.name = val;
    console.log("value: " + val);
});

您只需在 subscribe 回调中添加代码即可使用变化的值:

已编辑app.component.ts

import { Component } from '@angular/core';
import { MyService } from './my.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name;

  constructor(private _myservice: MyService) {
    this._myservice.isBoolean.subscribe(val => {
      console.log("value from subscribe: " + val);


      this.name = val ;
      if (val) {
        console.log("true!");
      } else if (!val) {
        console.log("false!");
      }
    })

  }
}

使用 Boolean BehaviorSubject 的正确方法 :-

这样定义:-

_isBoolean: BehaviorSubject<boolean> = new BehaviorSubject(false);

像这样更新:-

this._isBoolean.next(true); //  for true
this._isBoolean.next(false); // for false

读取其他组件中的值:-

this._isBoolean.subscribe(value => {
console.log(value);
    });

立即读取当前值一次:-

this._isBoolean.asObservable().pipe(take(1)).subscribe(value => {
    console.log(value);
  });

感谢 Rahmat Ali 带领我找到我需要的答案。我在这里提供一个答案,以便更容易找到,提供更简单的解决方案示例和更好的解释。

我想要一个 getter 函数,它允许我既可以订阅对 BehaviorSubject 值的更改,也可以根据当前需要在没有订阅的情况下获取当前值。

它不起作用的原因是在下面的另一个示例中,我将 getter return 设为 Observable 类型而不是 BehaviorSubject 类型。所以,我在控制台中得到了一个“真实”的结果,因为我正在检查它的存在而不是布尔值。一旦更改,我就可以使用 .value 属性.

访问 BehaviorSubject 的布尔值

这是一个简化的解决方案示例(注意:getter 是不必要的,因为一旦 getter return 编辑了 BehaviorSubject,我就可以使用 .next 更改它的值而不用创建 setter):

import { Component } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';

  private _isBooleanSubejct = new BehaviorSubject<boolean>(false);

  public get isBoolean(): BehaviorSubject<boolean> {
    return this._isBooleanSubejct;
  }

  constructor() {
    console.log(this.isBoolean.value);
    this.isBoolean.subscribe(val => {
      console.log(val); // false until the timer completed
      console.log(this.isBoolean.value); // false until the timer completed
    });

    setTimeout(() => {
      this.isBoolean.next(true);
    }, 5000);
  }
}