在我的项目中,我发现自己需要使用 WeakRefs 和 FinalizationRegistry,但我无法完全使其工作,所以我创建了一个简单的示例,但它也不起作用。你能帮我弄清楚为什么这个简单的例子不起作用:
示例代码:
let ref = new WeakRef({});
console.log("log", ref, ref.deref());
global.gc();
new Promise((res)=>{
setTimeout(()=>{res()}, 100_000)
}).then(()=>{
console.log("log2", ref, ref.deref());
})
global.gc();
console.log("log3", ref, ref.deref());
预期输出:
log WeakRef {} {}
log3 WeakRef {} undefined // maybe here still log3 WeakRef {} {}
log2 WeakRef {} undefined // here for sure!!!
实际输出:
log WeakRef {} {}
log3 WeakRef {} {}
log2 WeakRef {} {}
使用 global.gc() 不“强制”垃圾回收的替代方案也产生了上述结果。
我用来运行示例的命令:
node --expose-gc {filename}.js
如果是上面的代码或
node {filename}.js
在没有 global.gc() 的情况下运行测试时
我尝试过的节点版本:
17.9.1
20.10.0
21.7.3
WeakRef
值的代码期间,不会发生垃圾收集。也就是说,当您构造
new WeakRef(o)
或从
o = weakRef.deref()
获取对象时,直到您的代码运行完成为止
weakRef.deref()
将始终返回
o
。其间发生的垃圾收集周期(或使用
global.gc()
触发)无法收集该对象。因此您需要稍微延迟一下通话,将其放入您的
setTimeout
:
let ref = new WeakRef({});
// even when a garbage collection happens (by chance) here
console.log("log", ref, ref.deref()); // this will always return the object
setTimeout(() => {
global.gc(); // now it will be collected
console.log("log2", ref, ref.deref());
}, 100);