Angular 订阅未按预期运行-数组为空
我正在关注英雄示例的角度之旅,并(我认为)我的代码版本相同,但没有收到我期望的行为。
我的服务
<代码> 287670612myobserver(用于调试)
953662713
getports> getports(订阅到可观察的服务) >
debug Console
228942231
目标
目标是获取我从REST REST API接收的开关接口的列表(与Angular分开)并将它们分配到称为端口的字典列表。这应该在行中完成:
this.updateportsservice.getports()。问题
在函数范围内的英雄之旅中,应该填充示例端口。我已经从Wireshark和一些调试输出中确认了HTTP GET请求如预期的。具体来说,您可以看到该行:
this.updateportsservice.getports()。 (如预期)。但是,无论出于何种原因,
ports =&gt中的分配; this.ports = ports
似乎不起作用。端口的值始终是一个为零元素的空数组。但是,我无法弄清楚为什么。
这是一个在为异步数据赋值之前尝试访问异步数据的简单案例。在本例中,
this.ports
是异步赋值的。因此,当您执行
console.log(this.ports)
时,它尚未被赋值。但是当您使用
myObserver
时,它会起作用,因为您正在订阅内部打印,正如它应该的那样。使用
ports
的确切等效项将是以下内容
this.updateportsService.getPorts().subscribe(
ports => {
this.ports = ports;
console.log(this.ports);
},
error => {
// it is always good practice to handle error when subscribing to HTTP observables
}
);
请参阅 此处 了解有关异步请求的更多信息。
async
管道与控制器中的订阅
async
管道在大多数情况下都是推荐的,因为它负责取消订阅可观察对象,以避免内存泄漏问题。手动订阅可观察对象时,最好在
OnDestroy
钩子中取消订阅。
import { Subscription } from 'rxjs';
export class AppComponent implements OnInit, OnDestroy {
obsSubscription: Subscription;
ngOnInit() {
this.obsSubscription = this.service.observable.subscribe(value => { // handle value });
}
ngOnDestroy() {
if (this.obsSubscription) {
this.obsSubscription.unsubscribe();
}
}
}
使用
HttpClient
时通常会忽略
unsubscribe
,因为它处理取消订阅并避免内存泄漏。但是也有例外。例如,如果用户离开发出 HTTP 调用的链接,该链接可能仍处于打开状态。因此,始终建议手动关闭订阅。
还有另一种优雅的方式来处理取消订阅,即使用
takeUntil
。
import { Subject, pipe } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
export class AppComponent implements OnInit, OnDestroy {
closeActive = new Subject<void>();
ngOnInit() {
this.obsSubscription = this.service.observable
.pipe(takeUntil(this.closeActive))
.subscribe(value => { // handle value });
}
ngOnDestroy() {
this.closeActive.next();
this.closeActive.complete();
}
}
我不明白你的观察者调试,但我认为你应该更像这样做(你应该尽量避免手动订阅并使用异步管道,但这不是你的问题):
丢失调试观察者并在你的 getPorts 方法中执行以下操作:
this.updateportsService.getPorts().pipe(
tap(ports => console.log(ports),
tap(ports => this.ports = ports),
catchError(e => console.log(e)) // I suspect you'll catch some kind of error
).subscribe()
希望这有助于调试
That it receives a big array of objects (as expected). However, for whatever reason the assignment in ports => this.ports = ports does not seem to work. The value of ports is always an empty array with zero elements. However, I haven't been able to figure out why.
好吧,您使用
subscribe(myObserver);
您可以按照 @user3791775 的建议使用
pipe
和
tap
。
或者扩展您的观察者并在那里分配值。
const myObserver = {
next: ports => {
this.ports = ports;
console.log('Observer got a next value: ' + ports)
},
error: err => console.error('Observer got an error: ' + err),
complete: () => console.log('Observer got a complete notification'),
};
--编辑
实际上还有另一种解决方案
您可以创建
Subject
,它允许您处理多个订阅。
getPorts(): Subject<Port[]> {
const subject = new Subject<Port[]>();
return this.http.get<Port[]>(this.controller_ip + this.controller_url).subscribe(ports => subject.next(ports));
return subject;
}