JSPDF内存问题

JSPDF Memory Issue

我和我的团队在我们的应用程序中面临一个内存问题。问题是每当我们触发 jsPDF 实例它的工作但之后它持有大量内存并且我们面临性能问题因为它在任务完成后永远不会释放该内存。作为参考,我准备了一个例子,你可以检查一下。 https://stackblitz.com/edit/web-platform-vkewvw?file=index.html

所以在这个例子中你看到我的内存占用大约 36 MB 你可以在第一个屏幕截图上看到enter image description here

在 运行 之后,代码大约有 56MB,并且不会释放您在下一个屏幕截图中看到的内存。 enter image description here

任何人都可以帮助我们解决我们尝试使用 iframe 本身时无法正常工作的问题。

我们非常感谢您的帮助。

如评论中所述,更改撤销 blob url 的时间可能会改善使用 JSPDF 的应用程序中的内存处理,但不能保证这样做......


Blob 商店

用户代理维护 blob ULR store that keeps a reference to Blob objects keyed by the urls for them returned from URL.createObjectURL(blob)。在存储中保留一个引用会阻止从内存中收集垃圾 blob 对象,即使 JavaScript 代码 not 保留对 blob 对象本身的引用。

可以通过调用 URL.revokeObjectURL(blobURL) 将 blob 对象从 URL 存储中删除,之后如果在 JS 中无法访问 blob 的引用,则该 blob 有资格从内存中进行垃圾回收。

现在 jsPDFglobalObject.js, and imports the global object as _global in FileSaver.js.

的浏览器主 JavaScript 线程中将其全局对象设置为 window

FileSaver.js 的第 85 和 86 行将模块的 saveAs 导出定义为

var saveAs =
    _global.saveAs ||
    ... code for saving file

这意味着您应该能够 shim saveAs 函数 用于实验目的,通过声明一个 shim(使用 function saveAswindow.saveAs = ) 在文件级脚本 before 中,包括 HTML 文档中的 jsPDF.js

最初,您可以使用带有控制台日志的原始 saveAs 代码来证明匀场过程有效并且 jsPDF 仍然有效。我想看的东西包括

  • 是 jsPDF 同步 - 意思是它仅 return 到调用者 单击 saveAs 中的 link 以保存 PDF 文件之后生产?
  • 如果它可能是异步的,如何在单击 link 后从 shim 安排回调或承诺解决方案,以防止并行处理顺序生成的 PDF 文件。
  • 是否减少撤销 blob 之前的时间 URL,目前设置为 40 秒对于大多数浏览器 FileSave.js 的第 188 行(link 以上),对应用程序的性能有重大影响?
  • 应用程序 运行 在 Safari 和 ChromeIOS 中的表现如何,在 FileSave.js 中获得了出色的支持?

Blob 的同步撤销 URLs

Blob URLs 有可能在使用后被同步撤销。以下代码(不能用作代码片段)创建一个 blob 并下载它:

function blobURL(string) {
    const blob = new Blob(Array.from(string));
    return URL.createObjectURL(blob);  // see NOTE 1
}
    
const url = blobURL("hello folks and world");
console.log("2 seconds...");
setTimeout( saveBlob, 2000, url); // see NOTE 2

function saveBlob(url) {
    const link = document.createElement('a');
    link.setAttribute("download", "hello.txt");
    link.href= url;
    document.body.appendChild(link);
    link.click();
    URL.revokeObjectURL(url); // SEE NOTE 3
    console.log("Call to link.click() has returned");
}

备注

  1. 脚本不保留对创建的 blob 的引用
  2. 内存垃圾收集(理论上)可以在超时期间 运行。
  3. Blob 的 url 在 link.click() 之后、return 进入事件循环之前被同步撤销。

以编程方式单击 link 下载 blob 后立即调用 URL.revokeObjectURL() 不会影响在 Firefox 中下载成功或 Edge/webkit 测试时。这意味着这些浏览器 同步 获取对 Blob 实例的引用(使用 Blob Store 查找)before returning from link.click().

这与在同步处理的元素上以编程方式分派的事件的行为一致(我最近在回答 "Do events bubble in microtasks?" 时查看过)。然而,在生产中使用它的安全性并不是我个人能够在所有浏览器上保证的。