【发布时间】:2018-06-06 16:46:58
【问题描述】:
更新
由于提出了以下问题并在发现代码中的错误后得出了一个更基本的问题,我发现了一些更多信息,例如在 MDN Web 文档中下载 API 方法 downloads.download() 它声明撤销对象 url 应该只在 文件/url 被下载之后执行。因此,我花了一些时间试图了解 Web 扩展是否使下载 API onChanged 事件对网页的 javascript“可用”,但我认为它不会。我不明白为什么下载 API 仅可用于扩展,尤其是当有很多关于同一内存使用/对象 URL 撤销问题的问题时。例如,Wait for user to finish downloading a blob in Javascript。
如果你知道,请解释一下?谢谢。
从关闭 Firefox 浏览器开始,然后右键单击要在 Firefox 中打开的本地 html 文件,它会在 Windows 任务管理器中打开五个 firefox.exe 进程。其中四个进程的内存在 20,000k 到 25,000k 之间,一个进程的内存约为 115,000k。
这个 html 页面有一个 indexedDB 数据库,其中包含 50 个对象存储,每个存储包含 50 个对象。每个对象都从其对象存储中提取并使用 JSON.stringify 转换为字符串,然后写入二维数组。之后,将数组的所有元素连接成一个大字符串,转换为 blob 并通过 URL 对象写入硬盘,然后立即撤销。最终文件约为 190MB。
如果代码在转换为 blob 之前停止,则其中一个 firefox.exe 进程的内存使用量会增加到大约 425,000k,然后在数组元素被删除后大约 5-10 秒内回落到 25,000k连接成一个字符串。
如果代码运行完成,同一个 firefox.exe 进程的内存使用量会增长到大约 1,000,000k,然后下降到大约 225,000k。以 115,000k 开始的 firefox.exe 进程也在代码的 blob 阶段增加到大约 325,000k,并且从未减少。
在将 blob 作为文本文件写入磁盘后,这两个 firefox.exe 进程永远不会释放大约 2 x 200,000k 增加的内存。
我已将每个函数中使用的每个变量都设置为 null,除非刷新页面,否则永远不会释放内存。另外,这个过程是由一个按钮点击事件发起的;如果它在没有中间刷新的情况下再次运行,这两个 firefox.exe 进程中的每一个都会在每次运行时额外获取 200,000k 内存。
我还没弄清楚如何释放内存?
这两个功能非常简单。 json[i][j] 保存数据库中第 i 个对象存储中第 j 个对象的字符串版本。 os_data[] 是一个小对象数组 { "name" : objectStoreName, "count" : n },其中 n 是存储中的对象数。如果未调用 write_to_disk,则 build_text 函数似乎会释放内存。因此,问题似乎与 blob 或 url 有关。
我可能忽略了一些显而易见的事情。感谢您提供任何指导。
编辑:
我从JavaScript: Create and save file 看到我在 revokeObjectURL(blob) 语句中有错误。它不能撤销 blob,需要将 createObjectURL(blob) 保存到 url 之类的变量中,然后撤销 url,而不是 blob。
这在大多数情况下都有效,并且在大多数情况下,上述两个 firefox.exe 进程都会释放内存。这给我留下了一个关于撤销 url 时间的小问题。
如果撤销是允许释放内存的原因,是否应该仅在文件成功下载后撤销 url?如果撤销发生在用户单击确定下载文件之前,会发生什么?假设我单击按钮从数据库中准备文件,并且在准备好后浏览器会打开下载窗口,但是我等待了一会儿,考虑文件的名称或保存位置,撤销声明不会已经运行,但浏览器仍然“保留”url,因为它将下载什么?我知道我仍然可以下载文件,但撤销仍然释放内存吗?从我对这个示例的少量实验来看,它似乎没有在这种情况下发布。
如果有一个事件在文件成功或不成功地下载到客户端时触发,那不是应该撤销 url 的时间吗?在撤销 url 之前设置几分钟的超时会更好,因为我很确定没有事件表明下载到客户端已经结束。
我可能不了解这方面的基本内容。谢谢。
function build_text() {
var i, j, l, txt = "";
for ( i = 1; i <=50; i++ ) {
l = os_data[i-1].count;
for ( j = 1; j <= l; j++ ) {
txt += json[i][j] + '\n';
}; // next j
}; // next i
write_to_disk('indexedDB portfolio', txt);
txt = json = null;
} // close build_text
function write_to_disk( fileName, data ) {
fileName = fileName.replace(".","");
var blob = new Blob( [data], { type: 'text/csv' } ), elem;
if ( window.navigator.msSaveOrOpenBlob ) {
window.navigator.msSaveBlob(blob, fileName);
} else {
elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob);
elem.download = fileName;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
window.URL.revokeObjectURL(blob);
}; // end if
data = blob = elem = fileName = null;
} // close write_to_disk
【问题讨论】:
标签: javascript memory-leaks blob revokeobjecturl