Angular 角度:并发下载后内存泄漏?

Angular 角度:并发下载后内存泄漏?,angular,memory-leaks,download,observable,Angular,Memory Leaks,Download,Observable,我正在开发一个Angular应用程序,并创建了如下下载页面: 如果我看一下Chrome任务管理器,我会发现与我的应用程序相关的进程保留了大约130MB的内存 然后,用户可以单击每个下载按钮同时启动下载(总文件大小为266MB): 现在,如果我再次检查任务管理器,我会看到内存使用量增加,当所有下载完成时,其峰值约为650 MB。 我注意到一件奇怪的事情:内存的最终使用似乎是以下公式的总和: 初始内存使用率+2*总文件大小=最终内存使用率 130MB+2*266MB=130MB+532MB=66

我正在开发一个Angular应用程序,并创建了如下下载页面:

如果我看一下Chrome任务管理器,我会发现与我的应用程序相关的进程保留了大约130MB的内存

然后,用户可以单击每个下载按钮同时启动下载(总文件大小为266MB):

现在,如果我再次检查任务管理器,我会看到内存使用量增加,当所有下载完成时,其峰值约为650 MB。 我注意到一件奇怪的事情:内存的最终使用似乎是以下公式的总和:

初始内存使用率+2*总文件大小=最终内存使用率

130MB+2*266MB=130MB+532MB=662MB=~650MB。

如果我尝试使用Chrome垃圾收集器,它会减少大约30MB的内存,但我仍然有620MB的内存使用量。 那么,我如何纠正这种行为呢?你能看出我的代码有什么问题吗? (我曾尝试在组件的
ngondestory
上使用
unsubscribe
,但无效)

以下是当我单击文件的下载按钮(从下载页面)时调用的函数:

以下是
FileDownloadService
中的
downloadsfile
函数,由
getFile
调用:

downloadFile(file: SispFile): Observable<any> {
    let conf: any = {};
    conf.totalChunks = Math.max(Math.ceil(file.size / this.chunkSizeDownload), 1);
    conf.mime = file.extension;
    conf.currentChunk = 0;
    conf.byteDownloaded = 0;
    conf.chunkSizeDownload = this.chunkSizeDownload;
    conf.chunkBlobs = [];
    conf.finalBlob = null;

    file.progress = 0;

    return new Observable(observer => {
        observer.next(file);
        this.addChunk(file, observer, conf);
    })
}

addChunk(file: SispFile, observer: any, conf: any) {
    if (conf.currentChunk == conf.totalChunks) {
        observer.complete();
        conf.finalBlob = new Blob(conf.chunkBlobs, {type: conf.mime});

        let fileURL = URL.createObjectURL(conf.finalBlob);
        let a = document.createElement("a");
        a.href = fileURL;
        a.download = file.name;
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(fileURL);
    } else {
        this.docService.downloadFile(file, conf.chunkSizeDownload, conf.byteDownloaded)
            .then(response => {
                let typedArray = this.createBlob(response['_body'], conf.mime);
                conf.chunkBlobs[conf.currentChunk] = typedArray;
                conf.currentChunk++;
                conf.byteDownloaded = conf.currentChunk * conf.chunkSizeDownload;
                if (conf.Downloaded + this.chunkSizeDownload > file.size) {
                    conf.chunkSizeDownload = file.size - conf.Downloaded + 1;
                }

                let progress = Math.round((conf.currentChunk * 100) / conf.totalChunks);
                file.progress = progress;
                observer.next(file);
                this.addChunk(file, observer, conf);
            })
            .catch((error: ErrorMessage) => {
                observer.error(error);
                console.log('Errore server: ' + error);
            });
    }
}

我发现Angular有这个类。它的定义是:

可测试性服务提供可访问的测试挂钩 通过浏览器和诸如量角器之类的服务。每个都是自举的 页面上的Angular应用程序将具有可测试性实例

您可以通过访问特定元素的可测试性实例的全局注册表

正如我们在中所看到的,销毁组件不会释放浏览器的内存,因为可测试性API不会释放它的引用

因此,也许,通过清理destroy上的TestabilityRegistry可以帮助您摆脱那些导致620MB内存泄漏的引用

这是我找到的

我希望这有助于解决你的问题,或者至少我希望我能设法给你一个不同的观点或一个新的研究领域

更新:

据我所见,为了清理
可测试性注册表

在modules/@angular/core/src/testability/testability.ts中:

destroy(): void {
  this._applications.clear();
  testabilityGetter.onDestroy();
}
this._injector.get(TestabilityRegistry).destroy();
onDestroy(): void {
   delete global.getAngularTestability;
   delete global.getAllAngularTestabilities;
   delete global.getAllAngularRootElements;
   delete global.frameworkStabilizers;
}
这将是销毁方法

在模块/@angular/core/src/application\u ref.ts中:

destroy(): void {
  this._applications.clear();
  testabilityGetter.onDestroy();
}
this._injector.get(TestabilityRegistry).destroy();
onDestroy(): void {
   delete global.getAngularTestability;
   delete global.getAllAngularTestabilities;
   delete global.getAllAngularRootElements;
   delete global.frameworkStabilizers;
}
我们调用destroy方法

在modules/@angular/platform browser/src/browser/testability.ts中:

destroy(): void {
  this._applications.clear();
  testabilityGetter.onDestroy();
}
this._injector.get(TestabilityRegistry).destroy();
onDestroy(): void {
   delete global.getAngularTestability;
   delete global.getAllAngularTestabilities;
   delete global.getAllAngularRootElements;
   delete global.frameworkStabilizers;
}
销毁时,我们确保删除可测试性实例


看看。它向您展示了如何清理可测试性注册表。

感谢您的提示。那我该怎么办呢?我看到修复程序没有合并到Angular master repository。@smartmouse我相信您可以首先将其分叉并测试它是否修复了您的问题。也许你可以调整forked repository直到它满足你的需要。如果我尝试fork,那么你知道如何清理
TestabilityRegistry
?我确实看到了提交,我误解了你的答案,那么如果我将此修复应用到我的组件中,就没有必要在我的组件中执行任何操作。。。现在,我正在尝试将这些更改应用到我的存储库中……我确实尝试过使用修复程序,但它无法解决我的问题。无论如何,谢谢你的支持。(这是我修改的角度:)