【发布时间】:2020-01-18 10:24:24
【问题描述】:
这个问题看起来很长,但应该是一个很基础的rxjs问题。如果可以的话,请帮忙。
我正在编写一个 Angular 7 应用程序,其中包含如下服务、组件和模板,我想以一种简单的方式访问 observable 的最后一个值。
SoundMeterService
在服务中,我有一个私有 BehaviorSubject,我用它来使用“next”发出值。
我使用 .asObservable() 将此 BehaviorSubject 公开给消费者,以防止消费者执行 .next() 并发出新值。
在服务中,我使用 .value 访问 listeningStatusSubject 的当前值。
export type SoundMeterStatus = 'noResults' | 'isRunning' | 'hasResults';
export class SoundMeterService {
private listeningStatusSubject: BehaviorSubject<SoundMeterStatus> = new BehaviorSubject<SoundMeterStatus>('noResults');
get listeningStatus() { return this.listeningStatusSubject.asObservable(); }
// somewhere in the code I emit a different value
someFunc() {
if (this.listeningStatusSubject.value === 'noResults' )
this.listeningStatusSubject.next('isRunning');
}
}
SoundMeterComponent
遵循可观察对象的最佳实践,在组件中,我使用直接访问服务的可观察对象(通过listeningStatus getter),以便在模板中自动订阅和取消订阅(见下文)。
export class SoundMeterComponent {
serviceListeningStatus$ = this.sms.listeningStatus;
constructor(
private sms: SoundMeterService
) {}
ngOnInit() {
// I want to check the value of listeningStatus in a simple way without pulling the value out and saving it locally in SoundMeterComponent
}
}
SoundMeterTemplate
我正在使用 Angular 的异步管道,以便它在组件被销毁时自动订阅和取消订阅 observable(以避免here 提到的手动订阅)
<div *ngIf="(serviceListeningStatus | async) === 'noResults' ">
<span>some text</span>
</div>
我的问题
这种方法非常有效。但是我想在 ngOnInit() 中以简单的方式检查 listeningStatus 的值,而不是将值拉出并将其保存在 SoundMeterComponent 本地,并且不暴露 BehaviorSubject listeningStatusSubject 本身以使用 .value 检查其值,如所述下面:
1) 从服务中提取值并将其本地保存在 SoundMeterComponent 中:
SoundMeterComponent
export class SoundMeterComponent {
serviceListeningStatus$ = this.sms.listeningStatus;
private serviceListeningStatus;
constructor(
private sms: SoundMeterService
) {}
ngOnInit() {
// Pulling the value from the service:
this.sms.listeningStatus.subscribe( status => this.serviceListeningStatus = status ); // I'm trying to avoid this
if (this.serviceListeningStatus === 'noResults' ) {
displayNoResultsMessage();
}
}
}
2) 暴露 BehaviorSubject 本身并使用 .value 检查其值,如下所示:
SoundMeterService
export class SoundMeterService {
private listeningStatus: BehaviorSubject<SoundMeterStatus> = new BehaviorSubject<SoundMeterStatus>('noResults');
get listeningStatus() { return this.listeningStatus; }
}
SoundMeterComponent
export class SoundMeterComponent {
serviceListeningStatus = this.sms.listeningStatus;
constructor(
private sms: SoundMeterService
) {}
ngOnInit() {
if (this.sms.listeningStatus === 'noResults' ) {
displayNoResultsMessage();
}
}
}
SoundMeterTemplate
<div *ngIf="(serviceListeningStatus.asObservable() | async) === 'noResults' ">
<span>some text</span>
</div>
请帮助我了解哪种方法更好,同时保持简洁的代码。我知道关于如何从像 Simple way to get the current value of a BehaviorSubject with rxjs5 或 How to get current value of RxJS Subject or Observable? 这样的 BehaviorSubject 获取值有很多问题,但请注意,这是一个不同的问题。 谢谢!
【问题讨论】:
-
出现一个问题:我们真的要检查
onInit中的状态吗?你能确定在调用ngOninit时结果已经确定了吗?否则,由于我们通过异步管道订阅模板,我们可以在组件中的listeningStatus可观察对象上使用pipe和tap运算符,并在其中执行displayNoResultMessage()副作用。 -
原来它是一个 BehaviorSubject(即有一个初始值),所以是的,在 ngOnInit 中使用它是安全的。事实上,我在代码中的其他地方使用了
if(this.serviceListeningStatus === ... ),我希望listeningStatus已经被更改。如果我在代码中的其他3个地方使用它,你认为我还需要拉值并保存在本地吗? -
为什么不直接在 SoundMeterService 中公开当前状态(在行为主体上使用 .getValue() 返回具体值)?
标签: angular rxjs observable behaviorsubject