我想与多个组件共享一个状态(只是一个字符串)。为此,我遇到了this网站,并将其实施到我的应用中,如下所示:
my.component.ts
// ...
onButtonClick(event: MouseEvent) {
console.log('1');
this.myService.getStatus().subscribe(
(currentStatus) => {
console.log('2');
if (currentStatus=== 'success') {
// foo
} else {
// bar
}
},
(error) => { /* ... */ },
() => { /* ... */ }
);
console.log('3');
}
// ...
注意:我添加了console.logs进行调试。
这是我的服务
import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class MyService {
private status = new Subject<string>();
constructor() { }
getStatus(): Observable<string> {
return this.status .asObservable();
}
updateStatus(updatedStatus: string) {
this.status.next(updatedStatus);
}
}
我的问题是,我现在不明白,为什么在之后被解雇subscribe()?我用另一个按钮更新状态,所以调用堆栈类似于*Button Click* -> '1' -> '3' -> *btnUpdate click* -> '2'
。我确实早些时候调用过updateStatus()来设置一个值。
我在同一项目的其他地方使用了可观测对象,但它们的行为符合预期,这有何不同?
修改
这是供将来的读者使用的: 请参阅answer of Yevhenii Dovhaniuk,他使我对Observables有了更好的理解,他的回答也很有效
答案 0 :(得分:1)
涉及cold
和hot
可观察对象的定义,有关更多详细信息,请访问官方文档。
简而言之,您的Subject
是cold
可观察的意思是,它将在您每次订阅时执行,如果没有活动的atm订阅者,它将被销毁。
因此,要解决您的问题,可以在构造函数中添加订阅,例如
export class MyService implements OnDestroy {
private status = new Subject<string>();
private statusSubjectSubscription: Subscription;
constructor() {
this.statusSubjectSubscription = this.status.subscribe(); // here
}
ngOnDestroy() {
if (this.statusSubjectSubscription) {
this.statusSubjectSubscription.unsubscribe() // don't forget to unsubscribe
}
}
getStatus(): Observable<string> {
return this.status.asObservable();
}
updateStatus(updatedStatus: string) {
this.status.next(updatedStatus);
}
}
或将您的Subject的类型更改为ReplaySubject或BehaviorSubject(请注意,行为可能会更改)
答案 1 :(得分:1)
我不明白,为什么我用另一个按钮更新状态后会触发subscribe()
因为您使用的rxJs Subject
默认情况下不保存任何值,所以当您使用第一个按钮单击更新状态时,它不保存该值,并且当您单击另一个按钮进行更新时返回前一个值。举一个例子:
const subject = new Subject();
subject.next(1);
subject.subscribe(x => console.log(x));
此处控制台输出将为空。
因此,要解决此问题,您可能想使用最初拥有一个值的BehaviorSubject
,因此,当您订阅它时,它将立即返回该值。
看看here有关Subject
和BehaviorSubject
的更多细节。
答案 2 :(得分:1)
要完成先前的答案,您需要取消订阅Observable,以避免memory leaks
//Each time a subscribe is done, a Subscription is given in return
//Here your Subscription is lost leading to memory leak.
onButtonClick(event: MouseEvent) {
this.myService.getStatus().subscribe(...);
}
最好订阅ngOnInit并将Subscription存储在要在ngOnDestroy中销毁的类属性中
ngOnInit(){
this.subscription = this.myService.getStatus().subscribe(...);
}
ngOnDestroy(){
this.subscription.unsubscribe();
}
答案 3 :(得分:0)
我建议您使用onInit函数,因为现在单击按钮即可开始订阅。没有时间来完成下面的控制台日志,该控制台日志又在2之前打印1-> 3。