[英]Angular 8 subscribe fires after update
我想与多个组件共享一个 state(只是一个字符串)。 为此,我遇到了这个网站并将其实现到我的应用程序中,如下所示:
我的.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() 来设置一个值。
我在同一个项目的其他地方使用了 observables,但它们的行为符合预期,与这个有什么不同?
编辑
这是给未来的读者的:参考Yevhenii Dovhaniuk 的回答,他让我对 Observables 有了更好的理解,他的回答也很有效
关于cold
和hot
Observable 的定义,请访问官方文档了解更多详细信息。 简而言之,您的Subject
是cold
Observable 意味着每次您订阅它时都会执行它,并且如果没有订阅者活动 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);
}
}
或将您的主题类型更改为 ReplaySubject 或 BehaviorSubject(请注意,行为可能会改变)
我不明白,为什么 subscribe() 在我用另一个按钮更新状态后被触发
因为您使用的是 rxJs Subject
,默认情况下不保存任何值,所以当您使用第一个按钮单击更新状态时,它不会保存该值,当您单击另一个按钮进行更新时,它会返回以前的值。 给你举个例子:
const subject = new Subject();
subject.next(1);
subject.subscribe(x => console.log(x));
这里控制台 output 将为空。 因此,要解决此问题,您可能需要使用最初保存一个值的BehaviorSubject
,因此当您订阅它时,它将立即返回该值。
在此处查看有关Subject
和BehaviorSubject
的更多详细信息。
要完成之前的答案,您需要取消订阅 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 中订阅并将订阅存储在 class 属性中,该属性将在 ngOnDestroy 中销毁
ngOnInit(){
this.subscription = this.myService.getStatus().subscribe(...);
}
ngOnDestroy(){
this.subscription.unsubscribe();
}
我建议订阅您的 onInit 函数,因为订阅现在从您的按钮单击开始。 在下面的控制台日志之前没有时间完成,这反过来也会在 2 之前打印 1 -> 3。
最好的方法是退订。 访问以下链接
https://netbasal.com/when-to-unsubscribe-in-angular-d61c6b21bad3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.