Angular 中的 Observable
Observables in Angular
我正在尝试使用 Observable 来观察另一个 class 内部特定变量的更新。 class A,这将是被观察的部分,看起来像这样:
currentSheetNumber = 0;
public updateSheetNumber(): any {
const measurementDataObservable = new Observable(observer => {
observer.next(this.currentSheetNumber);
});
return measurementDataObservable;
}
想看变化的ClassB的代码是这样的:
sheetNumberObserver;
sheetNumber: number = 0;
ngAfterViewInit(): void {
this.sheetNumberObserver = this.measurementDataService.updateSheetNumber();
this.sheetNumberObserver.subscribe((sheets) => {
this.sheetNumber = sheets;
});
}
不幸的是,当我更改 class A 中的值 currentSheetNumber
时,Class B 的值 sheetNumber
没有改变。
有人知道问题出在哪里吗?
正如@jonrsharpe 指出的那样,就目前的情况而言,您的可观察对象只会发出一个值。听起来您想要的是一种在 currentSheetNumber
发生变化时通知订阅者的方法。这是一种可能性,分两步进行。首先,按照@jonrsharpe 的建议,让我们从您的服务中公开一个 Subject
(这是一种特殊的可观察对象):
public currentSheetNumber$ = new Subject();
然后,在class B:
ngAfterViewInit() {
this.sheetNumberObserver = this.measurementDataService.currentSheetNumber$.subscribe((sheets) => {
this.sheetNumber = sheets;
});
}
此时,只要将值“添加”到 currentSheetNumber$
主题,this.sheetNumber
(在 class B 中)将相应更新。
但是,目前 currentSheetNumber$
主题与您的 currentSheetNumber
变量(在您的服务中)没有任何关联。也就是说,当您更改 currentSheetNumber
时,currentSheetNumber$
不会发生任何变化。我们需要将这两者“绑定”在一起,以便 currentSheetNumber
的更新由 currentSheetNumber$
.
发出
实现此目的的一种方法是添加一种特殊方法来分配 currentSheetNumber
,并且 仅 使用该方法修改此变量。在这个方法中,我们可以同时更新 currentSheetNumber
和 向我们主题的订阅者发送新值:
setCurrentSheetNumber(value: number) {
// Update the value of `currentSheetNumber`...
this.currentSheetNumber = value;
// ...and send the new value to subscribers of `currentSheetNumber$`
this.currentSheetNumber$.emit(value);
}
这需要您将对 currentSheetNumber
的所有赋值替换为对 setCurrentSheetNumber
.
的调用
这应该可行,但它涉及遵循我们无法强制执行的纪律(不对变量进行“直接”赋值)。这是 difficult-to-diagnose 错误的潜在来源。
幸运的是,有一种方法可以稍微调整当前设置以提供更多 fool-proof 体验。我们可以用一对“getter/setter”方法替换currentSheetNumber
变量。这将允许我们在分配给 currentSheetNumber
时添加额外的“下一步”逻辑,而不必担心调用单独的方法:
get currentSheetNumber(): value {
// What goes here?
}
set currentSheetNumber(value: number) {
this.currentSheetNumber$.next(value);
}
现在,每当进行 this.currentSheetNumber = 42
之类的赋值时,新值(在本例中为 42
)将发送给 currentSheetNumber$
的所有订阅者。我们快到了。
我们需要解决的最后一个问题是:既然我们已经用 getter/setter 对替换了 currentSheetNumber
,我们实际上在哪里 存储 价值?我们有几种选择。一种是添加另一个变量,比如 _currentSheetNumber
,我们用它来维护当前值,但我们 从不直接与之交互 。看起来像这样:
_currentSheetNumber = 0;
get currentSheetNumber(): number {
return this._currentSheetNumber;
}
set currentSheetNumber(value: number) {
this._currentSheetNumber = value;
this.currentSheetNumber$.next(value);
}
这不仅增加了我们现在需要考虑的额外变量,我们又回到必须遵守与以前类似的分配规则:我们需要永不直接分配给 _currentSheetNumber
。必须有更好的方法。
有。我们需要做的就是使用 BehaviorSubject
而不是单纯的 Subject
。 BehaviorSubject
就像一个主题,但它“记住”了它的当前值,可以通过它的 getValue
方法访问它。这是它的样子:
public currentSheetNumber$ = new BehaviorSubject(0);
get currentSheetNumber(): number {
return this.currentSheetNumber$.getValue();
}
set currentSheetNumber(value: number) {
this.currentSheetNumber$.emit(value);
}
应该这样做,但是有一个重要的警告可能会导致错误和很多挫折。 BehaviorSubject
每当被订阅时都会发出其当前值。在许多情况下,这可能不是您想要的,并且它可能会迫使您添加一些错误(例如跳过订阅中的第一个发射值等)。在这种情况下,您最好使用 _currentSheetNumber
策略,尽管它有缺陷。
(或者,您可以 直接 与 currentSheetNumber$
行为主体互动并避免这种喧嚣, 或 编写一个保持其当前状态但不将其发送给新订阅者的自定义主题)
我正在尝试使用 Observable 来观察另一个 class 内部特定变量的更新。 class A,这将是被观察的部分,看起来像这样:
currentSheetNumber = 0;
public updateSheetNumber(): any {
const measurementDataObservable = new Observable(observer => {
observer.next(this.currentSheetNumber);
});
return measurementDataObservable;
}
想看变化的ClassB的代码是这样的:
sheetNumberObserver;
sheetNumber: number = 0;
ngAfterViewInit(): void {
this.sheetNumberObserver = this.measurementDataService.updateSheetNumber();
this.sheetNumberObserver.subscribe((sheets) => {
this.sheetNumber = sheets;
});
}
不幸的是,当我更改 class A 中的值 currentSheetNumber
时,Class B 的值 sheetNumber
没有改变。
有人知道问题出在哪里吗?
正如@jonrsharpe 指出的那样,就目前的情况而言,您的可观察对象只会发出一个值。听起来您想要的是一种在 currentSheetNumber
发生变化时通知订阅者的方法。这是一种可能性,分两步进行。首先,按照@jonrsharpe 的建议,让我们从您的服务中公开一个 Subject
(这是一种特殊的可观察对象):
public currentSheetNumber$ = new Subject();
然后,在class B:
ngAfterViewInit() {
this.sheetNumberObserver = this.measurementDataService.currentSheetNumber$.subscribe((sheets) => {
this.sheetNumber = sheets;
});
}
此时,只要将值“添加”到 currentSheetNumber$
主题,this.sheetNumber
(在 class B 中)将相应更新。
但是,目前 currentSheetNumber$
主题与您的 currentSheetNumber
变量(在您的服务中)没有任何关联。也就是说,当您更改 currentSheetNumber
时,currentSheetNumber$
不会发生任何变化。我们需要将这两者“绑定”在一起,以便 currentSheetNumber
的更新由 currentSheetNumber$
.
实现此目的的一种方法是添加一种特殊方法来分配 currentSheetNumber
,并且 仅 使用该方法修改此变量。在这个方法中,我们可以同时更新 currentSheetNumber
和 向我们主题的订阅者发送新值:
setCurrentSheetNumber(value: number) {
// Update the value of `currentSheetNumber`...
this.currentSheetNumber = value;
// ...and send the new value to subscribers of `currentSheetNumber$`
this.currentSheetNumber$.emit(value);
}
这需要您将对 currentSheetNumber
的所有赋值替换为对 setCurrentSheetNumber
.
这应该可行,但它涉及遵循我们无法强制执行的纪律(不对变量进行“直接”赋值)。这是 difficult-to-diagnose 错误的潜在来源。
幸运的是,有一种方法可以稍微调整当前设置以提供更多 fool-proof 体验。我们可以用一对“getter/setter”方法替换currentSheetNumber
变量。这将允许我们在分配给 currentSheetNumber
时添加额外的“下一步”逻辑,而不必担心调用单独的方法:
get currentSheetNumber(): value {
// What goes here?
}
set currentSheetNumber(value: number) {
this.currentSheetNumber$.next(value);
}
现在,每当进行 this.currentSheetNumber = 42
之类的赋值时,新值(在本例中为 42
)将发送给 currentSheetNumber$
的所有订阅者。我们快到了。
我们需要解决的最后一个问题是:既然我们已经用 getter/setter 对替换了 currentSheetNumber
,我们实际上在哪里 存储 价值?我们有几种选择。一种是添加另一个变量,比如 _currentSheetNumber
,我们用它来维护当前值,但我们 从不直接与之交互 。看起来像这样:
_currentSheetNumber = 0;
get currentSheetNumber(): number {
return this._currentSheetNumber;
}
set currentSheetNumber(value: number) {
this._currentSheetNumber = value;
this.currentSheetNumber$.next(value);
}
这不仅增加了我们现在需要考虑的额外变量,我们又回到必须遵守与以前类似的分配规则:我们需要永不直接分配给 _currentSheetNumber
。必须有更好的方法。
有。我们需要做的就是使用 BehaviorSubject
而不是单纯的 Subject
。 BehaviorSubject
就像一个主题,但它“记住”了它的当前值,可以通过它的 getValue
方法访问它。这是它的样子:
public currentSheetNumber$ = new BehaviorSubject(0);
get currentSheetNumber(): number {
return this.currentSheetNumber$.getValue();
}
set currentSheetNumber(value: number) {
this.currentSheetNumber$.emit(value);
}
应该这样做,但是有一个重要的警告可能会导致错误和很多挫折。 BehaviorSubject
每当被订阅时都会发出其当前值。在许多情况下,这可能不是您想要的,并且它可能会迫使您添加一些错误(例如跳过订阅中的第一个发射值等)。在这种情况下,您最好使用 _currentSheetNumber
策略,尽管它有缺陷。
(或者,您可以 直接 与 currentSheetNumber$
行为主体互动并避免这种喧嚣, 或 编写一个保持其当前状态但不将其发送给新订阅者的自定义主题)