WeakRefs cleanupSome ?
中文标题:WeakRefs 的 cleanupSome 方法
- 阶段: 未分阶段
- 状态: 已撤回
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案将 FinalizationRegistry.prototype.它解决了无需让出事件循环即可进行同步清理的需求,适用于 Workers 或 WebAssembly 中的长时间运行任务。设计已从返回布尔值和使用迭代器改为始终返回 undefined 并一次一个值地调用回调。将其拆分出来,为委员会讨论提供了更多时间,并明确了其在生态系统中的状态。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
FinalizationRegistry.prototype.cleanupSome 方法
提案发起人:Daniel Ehrenberg,Yulia Startsev
阶段 2
简介
FinalizationRegistry.prototype.cleanupSome 方法最初是 WeakRefs 提案的一部分。该方法为库作者提供了一种同步清理的方式,而无需让出事件循环。我们提议将其移入单独的提案,以便在添加这一额外功能之前,让 WeakRefs 的核心部分能够在实际环境中使用一段时间。
cleanupSome 的动机
WeakRef 和 FinalizationRegistry 允许 JavaScript 程序观察垃圾回收。这种可观察性带来了显著的互操作性风险,通过让宿主环境控制 JavaScript 何时能看到对象已被垃圾回收的时间粒度,可以在一定程度上限制这种风险。
在 HTML 中,粒度基于任务和微任务:WeakRefs 只允许在微任务检查点结束时(即所有 Promise 任务运行完毕后)从“包含对象”变为 undefined,而 FinalizationRegistry 的清理回调会在排队的任务中执行,这意味着也只有在所有 Promise 任务运行完毕后才会执行。这一切加起来就是:你需要定期让出事件循环,才能使 WeakRef 和 FinalizationRegistry 正常工作。
使用 Workers、SharedArrayBuffer 和/或 WebAssembly 线程/共享内存,可以创建“长任务”,它执行大量的计算,并通过共享内存和 Atomics 与其他代理通信,而不需要频繁地让出事件循环。WebAssembly 促进了这种用例。如果同时使用 JavaScript 垃圾回收对象,可能会有需求在不让出事件循环的情况下获取 FinalizationRegistry 的清理回调。
这个用例由 FinalizationRegistry.prototype.cleanupSome 满足。它接受一个函数作为参数(或者可以回退到 FinalizationRegistry 的回调),并且可以用任何已注册的、已被垃圾回收的值的 heldValue 来调用该回调,以同步执行清理操作。
犹豫:cleanupSome 何时应该暴露在 Web 上?
“长任务”的用例在 Web 的主线程“窗口”上不太合理。它更适合在后台 Worker/Worklet 线程上使用。因此,在浏览器中,将其排除在 window 之外可能是合理的。还有其他一些 Web 平台 API 只在某些全局对象的上下文中暴露,而不是全部暴露,因此这符合常见的惯例。
此外,Apple 对 cleanupSome 在 Web 上暴露提出了担忧,因为担心我们是否希望在同时使用对象的上下文中鼓励“长任务”的编程风格。
关于 cleanupSome 在浏览器中应该在哪里暴露以及是否应该暴露的讨论正在 WHATWG HTML issue 中进行。
将 cleanupSome 拆分为单独的提案,可以让每个人都有时间按照自己的节奏考虑它在浏览器中的存在。
随时间的设计变更
早期版本的 cleanupSome 与最新版本有以下不同:
- 最初,
cleanupSome返回一个布尔值以指示是否有任何内容被清理。现在,cleanupSome总是返回undefined。 - 最初,
cleanupSome用一个 held values 的迭代器调用其回调。JavaScript 代码可以选择不完全消耗迭代器,让引擎重新排队未使用的部分。现在,cleanupSome重复地、一次一个值地调用回调。
这些更改是在没有先前设计决策者参与的情况下进行的。将 cleanupSome 拆分为单独的提案,可以让委员会有时间重新考虑这些设计决策。
提案拆分与规范性可选相比的生态影响
声明 FinalizationRegistry.prototype.cleanupSome 从生态角度来看一直有些令人困惑。例如,
- TypeScript 类型定义 包含
cleanupSome但标记为可选 - MDN 文档 指出该方法是“可选的”,但读者不太清楚应该如何解释。
将 cleanupSome 拆分为单独的提案,将使 JavaScript 社区清楚 WeakRef 的主要部分已经是标准,而这一部分仍在讨论中。
委员会状态
FinalizationRegistry.prototype.cleanupSome 已从 WeakRefs 提案中移出,目前处于阶段 2。
历史
此 API 最初以特定于 WebAssembly 的形式提出。有关详细信息,请参见 历史文档 - 对长 wasm 作业的支持。