我是否总是需要显式调用URL.revokeObjectURL()?

Bas*_*ail 4 javascript garbage-collection memory-leaks blob

我正在使用blob下载文件,问题是即使下载文件后,我也希望保留对象URL,而无需在代码库中进行重大更改。

因此,一种选择是不致电 URL.revokeObjectURL();

依靠浏览器的垃圾回收器来避免任何内存泄漏是否安全?

我是否总是需要URL.revokeObjectURL();显式呼叫?

Kai*_*ido 6

另一个答案是正确的,但我认为为完整起见,我应该添加一些信息。

这主要取决于您传递给什么createObjectURL

  • 如果传递用户从中选择的文件<input type=file>,则您创建的blobURI是指向用户磁盘上文件的直接指针,此映射URI-file_path不会保存在内存中。因此,在这种情况下,您可以创建很多这样的应用程序而无需撤销它,而没有任何实际风险。

  • 如果您传递确实生成(或已获取)的Blob(或文件),则该Blob必须存储在内存中,并且blobURI实际上将始终是指向此Blob及其数据的指针,从而保护了它从GC,直到文档死亡。在这种情况下,当您不再需要它时,别忘了将其撤消。

  • 如果您传递的是来自用户设备的MediaStream,请不要这样做,它会被弃用,这有充分的理由:对于生成的Blob,UA必须在blobURI处于活动状态时保持与外部设备的连接打开,即使MediaStream已关闭,可能是连接仍处于打开状态并导致无法请求新连接。

  • @DashiellRoseBark-Huss,直到页面被导航离开或关闭。 (3认同)

the*_*472 5

依靠浏览器的垃圾回收器来避免任何内存泄漏是否安全?

createObjectURL大约要做的事是在创建的Blob URL中创建ID到Map与当前全局对象关联的隐藏中的实际Blob的映射。从GC的角度来看,这意味着Blob 保持可访问状态,直到全局本身变得可收集为止 -通常是在您离开页面或关闭选项卡时-或吊销了映射时(假定这是最后一个引用)。

因此,这取决于您认为什么泄漏。它不会在浏览器的生命周期内保持活动状态,而只会在当前页面的生命周期内保持活动状态。如果您希望其生存期可能短于当前页面,则需要撤销。

¹这并不是完全的实现方式,但是在推理可达性时,它可以很好地描述行为。