主要观点:在 Node 中使用setTimeoutAPI 易造成内存泄漏,Timeout对象内部实现细节会导致对象存活时间过长,从而引发内存泄漏问题,尤其是与AsyncLocalStorage结合使用时。
关键信息:
- 在浏览器中
setTimeout返回的令牌是number,而在 Node 中是Timeout对象,该对象内部持有一些超时实现的内部信息,导致垃圾回收器不会收集相关对象及其引用的内容。 AsyncLocalStorage会将额外状态附加到所有触发的超时上,使用越多AsyncLocalStorage,不清除超时就会持有越多“东西”。- 修复该问题的简单方法是持有底层 ID 而不是
Timeout对象,但目前 Node 存在一个bug导致此方法不可行。 - 可以通过 Monkey-Patch 方式在超时完成时强制清除超时或间隔来避免泄漏,但这会对
setTimeout和setInterval创建的每个定时器产生轻微影响。 - 也可以在不再需要超时令牌时手动删除它们。
- 像 Next.js 这样的项目也在尝试通过定期修补
setTimeout和setInterval来避免内存泄漏。 AsyncLocalStorage很有用,但容易意外持有内存,Node 可能需要改进以避免暴露内部Timeout对象,生态系统也需考虑摆脱上下文状态。
重要细节:
- 示例代码展示了
MyThing类中使用setTimeout和clearTimeout的方式,以及AsyncLocalStorage与Timeout对象的结合使用。 - 提到了
kHasPrimitive属性用于判断Timeout对象是否持有原始 ID。 - 解释了
console.log会意外持有调用的异步本地存储的相关问题。 - 标签为javascript。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。