问题:
我的应用程序在我加载的第一个组件上运行良好,当我点击切换到另一个组件时,它会在我的DAL上创建另一个订阅。
代码
servers.component.html<-默认组件
<div class="row">
<div class="col-md-12">
<app-server-list></app-server-list>
</div>
<router-outlet></router-outlet>
</div>
server-backup.component.html
<div class="row">
<div class="col-md-12">
<app-server-list ></app-server-list>
</div>
</div>
在server-list.component.ts中,我想每5秒刷新一次数据库中的数据,所以我这样做:
this.dataStorageService.getServerPerformanceInfo()
this.interval = setInterval(() =>
{
this.dataStorageService.getServerPerformanceInfo()
} , 5000)
当我在服务器和服务器备份之间切换时,我取消订阅:
ngOnDestroy()
{
this.subscriptions.forEach(subscription => {
subscription.unsubscribe();
});
clearInterval(this.interval);
}
最后在我的数据存储服务上。ts
getServerPerformanceInfo()
{
this.serverPerfSub = this.http.get<ServerPerformance[]>(DEV + '/getServerPerformance').subscribe
(
(data) => {
this.serversService.setPerformanceInfo(data);
}
)
}
当我在组件之间切换时,服务器列表组件被销毁、创建,但dataStorageService调用变得越来越频繁,直到我的API方法开始失败。
当然,这与dataStorageService上的订阅有关,但我该如何清理呢?
Javascript
您需要清除setInterval
。
interval: number;
ngOnInit() {
this.dataStorageService.getServerPerformanceInfo()
this.interval = setInterval(() => {
this.dataStorageService.getServerPerformanceInfo();
} , 5000);
}
ngOnDestroy() {
clearInterval(this.interval);
}
RxJS
这可以用javascript来完成,但我建议使用RxJSinterval
,因为您已经在处理可观察性了。
既然您想立即调用它,那么最好使用RxJStimer
。
// import { timer, Subject } from 'rxjs';
// import { takeUntil, catchError } from 'rxjs/operators';
private destroyed$ = new Subject();
ngOnInit() {
// start the timer and initiate the observable immediately.
// then emit a value every 5 seconds
timer(0, 5000).pipe(
// unsubscribe on ngOnDestroy
takeUntil(this.destroyed$)
).subscribe(() => {
// TODO: catch errors in data storage service
this.dataStorageService.getServerPerformanceInfo();
});
}
ngOnDestroy() {
this.destroyed$.next();
this.destroyed$.complete();
}
将订阅从您的服务中移出
不过,我建议将您的订阅从您的服务中删除。您仍然可以在tap
运算符中执行操作。您可以在组件中使用switchMap
将服务调用链接到timer
。
数据存储服务.ts
getServerPerformanceInfo(): Observable<any> {
const url = DEV + '/getServerPerformance';
return this.http.get<ServerPerformance[]>(url).pipe(
tap((data) => this.serversService.setPerformanceInfo(data))
);
}
组件.ts
ngOnInit() {
timer(0, 5000).pipe(
takeUntil(this.destroyed$),
switchMap(() => this.dataStorageService.getServerPerformanceInfo()),
catchError(error => of('An error has occured'))
).subscribe(() => {
// TODO: Something?
});
}
如果要捕获错误,可以使用catchError
在管道中捕获它们。我建议尽可能靠近源代码捕获它们——最好是在http请求之后不久。