问题描述
我正在调查一个问题,该问题似乎是由于“订阅”类的“取消订阅”方法似乎没有足够快地处理资源而造成内存泄漏的事实。
这是我的情况:
我有2个组件- LandingPageComponent (LPC)和 WebPlayerComponent (WPC)。 LPC是用户访问站点时看到的第一页。在该页面上,它们具有一个链接,可将它们带到第二页或WPC(传递参数,例如“ Operator Benchmarking ”)。用户单击浏览器的后退按钮可返回上一页。这会触发WPC的 ngOnDestroy 方法,该方法将处理订阅(请参见下面的代码)。
WebPlayerComponent
export class WebPlayerComponent implements OnInit,OnDestroy {
@input() workbookId: string;
@input() workbookPage: string | number;
private _workbooks: Workbook[];
private _filters: Filter[];
private _subscriptions: { [key: string]: Subscription } = {};
ngOnInit() {
this._subscriptions["combined"] = combineLatest(
this.workbookService.workbooks$,this.filterService.filters$,this.libraryService.userFolderInitialised$
).subscribe(([workbooks,filters,userFolderInitialised]) => {
this._workbooks = workbooks;
this._filters = filters;
this._subscriptions["webPlayerServiceSubscription"] = this.webPlayerService.openWorkbook(workbook.libraryPath,parameterString).subscribe(
(webPlayer) => {
console.log("_subscriptions before 'openWorkbook call'");
Object.keys(this._subscriptions).map((key) => {
console.log(key);
});
console.log("Openning document page: " + this.workbookPage);
webPlayer.opendocument("spotfire-container",this.workbookPage);
});
});
}
ngOnDestroy() {
Object.keys(this._subscriptions).map((key) => {
this._subscriptions[key].unsubscribe();
console.log("---Unsubscribed " + key + "---");
});
}
}
如果用户单击浏览器的“后退”按钮并足够快地单击“链接”,则问题开始出现(在我的示例中,该时间少于5秒)。本应被处置的订阅不是并且仍处于活动状态。我可以通过查看控制台的输出来确认这一点:
在上图中,您可以看到在再次点击 LandingPageComponent 上的“链接”后,我们看到了两组呼叫(绿色数字(1)和(2)),参见“打开文档页面:” 3次
我不确定为什么我的订阅资源处理得不够快(至少我认为这是这里的问题)。
注意:我正在使用 RxJS 6.4.0 和 Angular 8.1.3
解决方法
您可以像使用switchMap
:
ngOnInit() {
this._subscriptions["combined"] = combineLatest(
this.workbookService.workbooks$,this.filterService.filters$,this.libraryService.userFolderInitialised$
)
.pipe(
switchMap(([workbooks,filters,userFolderInitialised]) => {
this._workbooks = workbooks;
this._filters = filters;
return this.webPlayerService.openWorkbook(workbook.libraryPath,parameterString)
})
)
.subscribe((webPlayer) => {
webPlayer.openDocument("spotfire-container",this.workbookPage);
});
}
因此,您将可观察范围从combineLatest
更改为openWorkbook