ngOnDestroy中的RxJS“取消订阅”方法无法足够快地处理资源

问题描述

我正在调查一个问题,该问题似乎是由于“订阅”类的“取消订阅方法似乎没有足够快地处理资源而造成内存泄漏的事实。

这是我的情况:

enter image description here

我有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秒)。本应被处置的订阅不是并且仍处于活动状态。我可以通过查看控制台的输出来确认这一点:

enter image description here

在上图中,您可以看到在再次点击 LandingPageComponent 上的“链接”后,我们看到了两组呼叫(绿色数字(1)和(2)),参见“打开文档页面:” 3次

如果我等待5秒钟然后再次单击链接,则输出应该是这样

enter image description here

我不确定为什么我的订阅资源处理得不够快(至少我认为这是这里的问题)。

注意:我正在使用 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