BehaviorSubject .next() 没有发出更新的值
BehaviorSubject .next() is not emitting updated value
我只是想为我对 RxJS 和 Observables 的缺乏理解而道歉。我之前发布了一个问题,但它的措辞很糟糕,我知道它无法理解,所以一天后我想我可以更好地解释我的问题。
- 我的代码的 objective 是获取用户输入,将其作为动作流传递到我的数据流,将输入与我的托架数组进行比较,如果存在,return单湾。如果它不存在 (这是我挣扎的地方) return 我可以在我的
bay.page.ts
中回调并检查它是否true
或 false
。如果是 false
[显示客户端错误]。
如果是 true
,请向前导航至结果页面。
- 我的
bay-service.ts
class 包含我的数据和操作流:
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);
}
^ 在上面的代码中,我使用了一种声明式 RxJS 方法 selectedBay$
,其中我结合了我的 bay$
数据流和我的 baySelectedAction$
动作流(其中包含用户输入) .然后我映射它们,然后将用户输入 selectedBayNumber
与单个托架编号进行比较。
问题: 我正在尝试使用我在 bay-service.ts
中创建的 Observable -> invalidBay = new BehaviorSubject<boolean>(false);
并检查它的结果:如果它是真的, 向前导航。如果它是 false,则显示它不存在的客户端错误。 但是,如果用户输入有效的托架编号,我尝试通过 this.invalidBay.next(true);
将 Observable 更改为 true
但是,Observable 不会更新它的值? BehaviorObservable 保持其默认值 'false'。所以代码部分有效,但不是完全有效。
- 这是我
bay-page.ts
中的 onSubmit
方法,我在其中处理我的操作流的用户输入。我将用户输入传递给一个方法(在我的 bay-service.ts
class 中)。根据他们的输入,我尝试订阅“应该更新”的 Observable,然后从那里开始。但是 Observable 没有被更新。请帮助。
onSubmit() {
this.bayService.selectedBayChanged(this.bayForm.get('bayStart').value);
this.subscription = this.bayService.invalidBay.subscribe(value => {
if (value) {
this.navCtrl.navigateForward([`/results/`]);
} else {
this.bayDoesNotExistError = true;
this.selectedBay = this.bayForm.get('bayStart').value;
this.vibration.vibrate(500);
console.log('Vibrating for 3 second...')
}
})
}
为什么 Observable 没有更新它的值?拜托,我的心很痛,我不知道还能做什么。
如果没有观察者订阅,则 Observable 不执行任何操作。您没有订阅 selectedBay$
可观察对象。因此,来自 combineLatest
的管道中的代码根本没有执行,无论新值被发送到您的操作流多少次,并且您总是从 [=18= 接收初始 false
值].
一些建议:
A BehaviorSubject
是一个多播可观察对象,您应该始终将其保密以最小化对其调用 next()
的范围。使用 .asObservable()
方法将其公开为可观察对象,如果任何外部代码需要能够发出新值,请提供 public 方法来执行此操作。您已经在以这种方式处理 baySelectedSubject
。考虑对 invalidBay
.
做同样的事情
切勿将您的订阅代码放在会执行多次的方法中。每次执行该方法时,您最终都会创建一个新订阅。可观察对象将为每个订阅发出值。因此,从 onSubmit()
中删除您的订阅并将其放入 ngOnInit()
.
如果您不需要它,请避免存储 Subscription
引用。您可以简单地订阅为 -
this.bayService.invalidBay$.subscribe(value => ...
而不是-
this.subscription = this.bayService.invalidBay.subscribe(value => ...
万一你做需要一个Subscription
引用,那么记得在ngOnDestroy
方法中做清理-
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
一旦您的组件被销毁,这将取消订阅 observable。否则,即使在您的组件被销毁后,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);
}
}
在你的组件中 -
ngOnInit(): void {
this.bayService.selectedBay$.subscribe(
p => {
// do something with the Bay value
}
);
this.bayService.invalidBay$.subscribe(
p => {
// do something with the invalidBay value
}
);
}
onSubmit(): void {
this.bayService.selectedBayChanged(this.bayForm.get('bayStart').value);
}
ngOnDestroy(): void {
// if you stored Subscription reference
this.subscription.unsubscribe();
}
我只是想为我对 RxJS 和 Observables 的缺乏理解而道歉。我之前发布了一个问题,但它的措辞很糟糕,我知道它无法理解,所以一天后我想我可以更好地解释我的问题。
- 我的代码的 objective 是获取用户输入,将其作为动作流传递到我的数据流,将输入与我的托架数组进行比较,如果存在,return单湾。如果它不存在 (这是我挣扎的地方) return 我可以在我的
bay.page.ts
中回调并检查它是否true
或false
。如果是false
[显示客户端错误]。 如果是true
,请向前导航至结果页面。 - 我的
bay-service.ts
class 包含我的数据和操作流:
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);
}
^ 在上面的代码中,我使用了一种声明式 RxJS 方法 selectedBay$
,其中我结合了我的 bay$
数据流和我的 baySelectedAction$
动作流(其中包含用户输入) .然后我映射它们,然后将用户输入 selectedBayNumber
与单个托架编号进行比较。
问题: 我正在尝试使用我在 bay-service.ts
中创建的 Observable -> invalidBay = new BehaviorSubject<boolean>(false);
并检查它的结果:如果它是真的, 向前导航。如果它是 false,则显示它不存在的客户端错误。 但是,如果用户输入有效的托架编号,我尝试通过 this.invalidBay.next(true);
将 Observable 更改为 true
但是,Observable 不会更新它的值? BehaviorObservable 保持其默认值 'false'。所以代码部分有效,但不是完全有效。
- 这是我
bay-page.ts
中的onSubmit
方法,我在其中处理我的操作流的用户输入。我将用户输入传递给一个方法(在我的bay-service.ts
class 中)。根据他们的输入,我尝试订阅“应该更新”的 Observable,然后从那里开始。但是 Observable 没有被更新。请帮助。
onSubmit() {
this.bayService.selectedBayChanged(this.bayForm.get('bayStart').value);
this.subscription = this.bayService.invalidBay.subscribe(value => {
if (value) {
this.navCtrl.navigateForward([`/results/`]);
} else {
this.bayDoesNotExistError = true;
this.selectedBay = this.bayForm.get('bayStart').value;
this.vibration.vibrate(500);
console.log('Vibrating for 3 second...')
}
})
}
为什么 Observable 没有更新它的值?拜托,我的心很痛,我不知道还能做什么。
如果没有观察者订阅,则 Observable 不执行任何操作。您没有订阅 selectedBay$
可观察对象。因此,来自 combineLatest
的管道中的代码根本没有执行,无论新值被发送到您的操作流多少次,并且您总是从 [=18= 接收初始 false
值].
一些建议:
A
做同样的事情BehaviorSubject
是一个多播可观察对象,您应该始终将其保密以最小化对其调用next()
的范围。使用.asObservable()
方法将其公开为可观察对象,如果任何外部代码需要能够发出新值,请提供 public 方法来执行此操作。您已经在以这种方式处理baySelectedSubject
。考虑对invalidBay
.切勿将您的订阅代码放在会执行多次的方法中。每次执行该方法时,您最终都会创建一个新订阅。可观察对象将为每个订阅发出值。因此,从
onSubmit()
中删除您的订阅并将其放入ngOnInit()
.如果您不需要它,请避免存储
Subscription
引用。您可以简单地订阅为 -
this.bayService.invalidBay$.subscribe(value => ...
而不是-
this.subscription = this.bayService.invalidBay.subscribe(value => ...
万一你做需要一个Subscription
引用,那么记得在ngOnDestroy
方法中做清理-
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
一旦您的组件被销毁,这将取消订阅 observable。否则,即使在您的组件被销毁后,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);
}
}
在你的组件中 -
ngOnInit(): void {
this.bayService.selectedBay$.subscribe(
p => {
// do something with the Bay value
}
);
this.bayService.invalidBay$.subscribe(
p => {
// do something with the invalidBay value
}
);
}
onSubmit(): void {
this.bayService.selectedBayChanged(this.bayForm.get('bayStart').value);
}
ngOnDestroy(): void {
// if you stored Subscription reference
this.subscription.unsubscribe();
}