如何解决BehaviorSubject .next() 未发出更新值
我只是想为我对 RxJS 和 Observables 缺乏了解而道歉。我之前发布了一个问题,但措辞很差,我知道这是无法理解的,所以一天后我想我可以更好地解释我的问题。
- 我的代码的目标是获取用户输入,将其作为动作流传递给我的数据流,将输入与我的托架数组进行比较,如果存在,则返回该单个托架。如果它不存在(这是我苦苦挣扎的地方)返回一个可观察的对象,我可以在我的
bay.page.ts
中调用它并检查它的true
或 { {1}}。如果是false
[显示客户端错误]。 如果是false
,请向前导航到结果页面。 - 我的
true
类包含我的数据和操作流:
bay-service.ts
^ 在上面的代码中,我使用了声明式 RxJS 方法 export class BayServiceService {
private baysUrl = 'api/bays';
bays$ = this.http.get<Bay[]>(this.baysUrl)
.pipe(
tap(data => console.log('Bays: ',JSON.stringify(data))),catchError(this.handleError)
);
/*--------------------------------------------------------------*/
// Grab A Single Bay
private baySelectedSubject = new BehaviorSubject<number>(0);
baySelectedAction$ = this.baySelectedSubject.asObservable();
invalidBay = new BehaviorSubject<boolean>(false);
selectedBay$ = combineLatest([
this.bays$,this.baySelectedAction$
])
.pipe(
map(([bays,selectedBayNumber]) => {
if (!bays.find(bay => bay.bayCode === selectedBayNumber)){
this.invalidBay.next(false);
} else {
this.invalidBay.next(true);
return bays.find(bay => bay.bayCode === selectedBayNumber);
}
}),);
selectedBayChanged(selectedBayNumber: number): void {
this.baySelectedSubject.next(selectedBayNumber);
}
,其中我将 selectedBay$
数据流和 bay$
操作流(其中包含用户输入)组合在一起。然后我将它们映射,然后将用户输入 baySelectedAction$
与单个托架编号进行比较。
问题:我正在尝试使用我在 selectedBayNumber
中创建的 Observable -> invalidBay = new BehaviorSubject<boolean>(false);
并检查它的结果:如果为真,则向前导航。如果它是假的,则显示它不存在的客户端错误。 但是,如果用户输入有效的托架编号,我会尝试通过执行 bay-service.ts
将该 Observable 更改为 true
但是,Observable 不会更新它的值? BehaviorObservable 保持其默认值“false”。所以代码部分工作,但不完全。
- 这是我的
this.invalidBay.next(true);
中的onSubmit
方法,我在其中处理操作流的用户输入。我将用户输入传递给一个方法(在我的bay-page.ts
类中)。根据他们的输入,我尝试订阅“应该更新”的 Observable 并从那里开始。但是 Observable 没有被更新。请帮忙。
bay-service.ts
为什么 Observable 的值没有更新?拜托,我的心很痛,我不知道还能做什么。
解决方法
如果没有观察者订阅一个可观察对象,则它什么也不做。您没有订阅 selectedBay$
可观察对象。因此,来自 combineLatest
的管道中的代码根本没有执行,无论新值向您的操作流发出多少次,并且您始终从 {{1} 接收初始 false
值}.
一些建议:
-
invalidBay
是一个多播的 observable,你应该始终保持它的私密性,以尽量减少在它上面调用BehaviorSubject
的范围。使用next()
方法将其公开为 observable,如果任何外部代码需要发出新值的能力,请提供一个公共方法来执行此操作。您已经在以这种方式处理.asObservable()
。考虑对baySelectedSubject
做同样的事情。 -
切勿将您的订阅代码放在将执行多次的方法中。每次执行该方法时,您最终都会创建一个新订阅。 observable 将向每个订阅发出值。因此,请从
invalidBay
中删除您的订阅并将其放入onSubmit()
。 -
如果您没有使用它,请避免存储
ngOnInit()
引用。您可以简单地订阅为 -
Subscription
代替 -
this.bayService.invalidBay$.subscribe(value => ...
如果你确实需要一个 this.subscription = this.bayService.invalidBay.subscribe(value => ...
引用,那么记得在 Subscription
方法中进行清理 -
ngOnDestroy
一旦您的组件被销毁,这将取消订阅 observable。否则,即使您的组件被销毁,ngOnDestroy(): void {
this.subscription.unsubscribe();
}
引用仍会保留可观察对象,这最终会导致内存泄漏。
基于建议的(相对)更好的实施:
服务-
Subscription
在您的组件中 -
export class BayServiceService {
private baysUrl = 'api/bays';
bays$ = this.http.get<Bay[]>(this.baysUrl)
.pipe(
tap(data => console.log('Bays: ',JSON.stringify(data))),catchError(this.handleError)
);
private baySelectedSubject = new BehaviorSubject<number>(0);
baySelectedAction$ = this.baySelectedSubject.asObservable();
private invalidBay = new BehaviorSubject<boolean>(false);
invalidBay$ = this.invalidBay.asObservable();
selectedBay$ = combineLatest([this.bays$,this.baySelectedAction$])
.pipe(
map(([bays,selectedBayNumber]) => {
let bay = bays.find(p => p.bayCode === selectedBayNumber);
if (!bay) {
this.invalidBay.next(false);
} else {
this.invalidBay.next(true);
return bay;
}
}));
selectedBayChanged(selectedBayNumber: number): void {
this.baySelectedSubject.next(selectedBayNumber);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。