更新
由于在代码中发现错误后提出了以下问题并得出了一个更基本的问题,因此我发现了更多信息,例如在 MDN Web 文档中的下载 API 方法 downloads.download() 它声明对象的撤销url 应仅在文件/url 下载后执行。因此,我花了一些时间试图了解 Web 扩展是否使下载 API onChanged 事件对网页的 javascript“可用”,但我认为它不会。我不明白为什么下载 API 仅可用于扩展,尤其是当有很多关于同一内存使用/对象 URL 撤销问题的问题时。例如,等待用户完成 Javascript 中的 blob 下载。
如果你知道,请解释一下好吗?谢谢你。
从关闭 Firefox 浏览器开始,然后右键单击要在 Firefox 中打开的本地 html 文件,它会打开五个 firefox.exe 进程,如在 Windows 任务管理器中所见。其中四个进程的内存在 20,000k 到 25,000k 之间,一个进程的内存约为 115,000k。
这个 html 页面有一个 indexedDB 数据库,其中包含 50 个对象存储,每个存储包含 50 个对象。每个对象都从其对象存储中提取并使用 JSON.stringify 转换为字符串,然后写入二维数组。之后,将数组的所有元素连接成一个大字符串,转换为 blob 并通过 URL 对象写入硬盘,然后立即撤销。最终文件约为 190MB。
如果代码在转换为 blob 之前停止,则其中一个 firefox.exe 进程的内存使用量会增加到大约 425,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