You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blob对象与createObjectURL的GC问题及自动撤销URL实现方案

问题解答

1. Blob的垃圾回收规则

当调用URL.createObjectURL(blob)时,浏览器会在内部保留对该Blob的引用——哪怕你的代码里已经没有Blob的变量引用,这个Blob也不会被垃圾回收,直到你主动调用URL.revokeObjectURL(url)撤销该URL,或者页面卸载时才会释放。

看你给出的第一个代码示例:

async function getImageBlobURL() {
  const res = await fetch('/image.png');
  const blob = await res.blob(); // will it be GCed?
  const url = URL.createObjectURL(blob);
  return url;
}

const img = document.createElement('img');
const url = await getImageBlobURL();
img.url = url;
document.body.append(img);

函数执行完毕后,blob变量的作用域结束,但由于url对应的内部引用仍存在,这个Blob不会被GC,会持续占用内存,直到页面关闭或你主动调用撤销方法。

2. 自动撤销URL的实现说明

你用FinalizationRegistry实现自动撤销的思路是可行的,但有几个关键注意点:

  • FinalizationRegistry的回调执行时机不确定,浏览器不会保证Blob被标记为垃圾后立刻触发回调,可能存在延迟,极端场景下甚至不会执行。
  • 必须确保使用URL的代码同时持有Blob的引用(如示例中的img._blobObj = blob),否则若Blob先被GC但图片仍在使用URL,会导致图片加载失败。

你的实现代码可以正常工作,但要明确其局限性:

const finalizationRegistry = new FinalizationRegistry<string>((url) => {
  URL.revokeObjectURL(url);
});

/**
 * 获取Blob的URL,当Blob被垃圾回收时会自动撤销该URL。
 * 使用此URL的代码必须同时持有该Blob的引用。
 */
export function getAutoRevokableBlobUrl(blob: Blob) {
  const url = URL.createObjectURL(blob);
  finalizationRegistry.register(blob, url);
  return url;
}

// 使用示例:
const img = document.createElement('img');
const url = getAutoRevokableBlobUrl(blob);
img.url = url;

// 当img被移除并垃圾回收后,blob也会被回收,URL会在FinalizationRegistry中自动撤销
img._blobObj = blob; 

document.body.append(img);

如果是对内存占用敏感的场景(比如处理大量Blob资源),建议还是主动调用URL.revokeObjectURL及时释放内存,不要完全依赖FinalizationRegistry的自动回调。

内容的提问来源于stack exchange,提问作者DisLido

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 07:32:11