【问题标题】:Angular 9: Observable Getter Returning Object Instead of Boolean from BehaviorSubjectAngular 9:可观察的 Getter 返回对象而不是来自 BehaviorSubject 的布尔值
【发布时间】:2020-08-04 16:52:56
【问题描述】:

如果此问题发布在 Stack Overflow 上的某个地方,我深表歉意,但我找不到适合我的答案。

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

我尝试过使用 .getValue(),它似乎不起作用,我尝试过 .value,它似乎确实有效,但在 IDE 中引发错误。

我创建了一个非常基本的示例来说明我正在尝试完成的工作,并将 cmets 放入 my.service.ts 文件中以显示我的目标。请指教。谢谢!

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

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

编辑:我还添加了 .subscribe 以表明虽然我了解 Observables 的工作方式,但如果可能的话,我还想使用相同的 getter 检查值更改的外部值。

我的服务

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
  }

}

应用组件

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

【问题讨论】:

  • 你应该把你的代码放在你的答案中
  • 为此,需要定义新的值,如 (subjectBoolean)。并且每当向 BehaviorSubject 发出值时,将那个 subjectBoolean 值设置在一起并在 getter 方法上返回那个 subjectBoolean。
  • @Derek.W 你能举一个编码的例子吗?我不听你说的。谢谢。
  • 或者你可以在MyService上得到这样的值:this._isBoolean.getValue(),那么它就可以工作了。
  • 可以直接使用BehaviorSubject,不需要使用observable。因此,最好将 BehaviorSubject 变量设为公共,并在 getIsBoolean 上仅使用 BehaviorSubject.getValue() 返回 rela 布尔值

标签: angular observable getter angular9 behaviorsubject


【解决方案1】:

您以错误的方式使用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!");
      }
    })

  }
}

【讨论】:

  • 谢谢你,拉赫马特。虽然我在代码的某些区域使用订阅(示例中未显示,因为那里不存在错误),但我也在尝试使用 getter 来获取当前值,而不仅仅是在值更改时。是我在尝试获取 BehaviorObject 的当前值时无法拥有 Observable getter 的问题吗?
  • BehaviorSubject 用于获取我们subscribe 时的初始值。因此,当我们将subscribe 调用应用到BehaviorSubject 时,subscribe 函数将具有当前值。您不必在此处使用getter,因为它不是必需的。请检查更新的stackbliz以清除BehaviorSubject的用法:link
  • BehaviorSubject 的目的是稍后可以通过另一种方法更改该值,我希望能够通过 subscribe 方法对这些更改做出反应。在初始化后,我没有在示例代码中添加任何内容来更改它,因为这不是我正在努力解决的部分。我希望能够看到当前值而不必订阅 getter。否则,每次值更改时,都会有另一种处理值更改的方法。我说得有道理吗?它开始听起来像是需要另一个不可观察的吸气剂。
  • 您可以使用.value getter 获取当前值。随时在BehaviorSubject 上使用它,您将拥有当前价值。但是您正在从您的服务调用一个函数,该函数返回Observable (isBoolean(): Observable&lt;boolean&gt;),如果您将返回类型更新为BehaviorSubject&lt;boolean&gt;any,它也适用于回调。
  • @AncientSpice,如果您不想将函数的返回类型从Observable 更新为另一个,您也可以使用pipe 并按照@abhay tripathi 的建议添加take(1)
【解决方案2】:

正确的方式使用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);
  });

【讨论】:

  • 价值变化之外是什么意思?
  • 即使值不会自动更改,您仍然希望获取该值。我对吗 ?为此,您还必须订阅它,它会立即产生价值。
【解决方案3】:

问题在于应用程序的 html 部分,该服务返回一个模板必须订阅的 observable。为此,您必须将异步管道添加到模板变量

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

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

【讨论】:

  • 虽然我很感谢您的反馈,但恐怕它错过了我的问题的重点。并不是我看不到 HTML 中的值。这是 getter 返回一个 Object 而不是布尔值。即使我只是在控制台中编写对 getter 的调用,也会发生这种情况。对不起,我不是更清楚。
  • 在订阅中发生可观察值的任何时候返回。如果你想要一些基于 isBoolean 的 vbalue 的逻辑,那么你也必须订阅服务中的 observable
【解决方案4】:

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

我想要一个 getter 函数,它允许我订阅对 BehaviorSubject 值的更改,还能够根据当前需要在不订阅的情况下获取当前值。

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

这是解决方案的简化示例(注意:getter 是不必要的,因为一旦 getter 返回 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);
  }
}

【讨论】:

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