主要观点:在 Node 中使用setTimeout
API 易造成内存泄漏,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) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。