我正在使用在V8中,并且无法验证下面的代码在Node.js中实际工作。
我使用Nodev15.3.0并像这样运行它:
node --expose-gc transient.js
我希望在控制台日志中看到一些finalizerCallback called!条目。
如果我在基于Chrome的浏览器中运行它(尝试Run code snippet按钮),如果在DevTools的性能部分(在Chrome v87中)单击垃圾图标(收集垃圾),而异步脚本仍在运行,我就可以获得这个输出。
在火狐v83中,我看到脚本结束时所有的终结器回调都能正常工作。
使用Node时,我希望在显式调用垃圾收集时自动看到它,但是终结器回调根本没有被调用。
代码本身是否有任何问题,或者是否有一种更可靠的方法来强制节点中的GC?
// by @noseratio
// see https://v8.dev/features/weak-references
class Transient {
constructor(eventTarget) {
const finalizerCallback = ({ eventTarget, eventListener }) => {
console.log('finalizerCallback called!');
eventTarget.removeEventListener('testEvent', eventListener);
}
const finalizer = new FinalizationRegistry(finalizerCallback);
const strongRefs = { finalizer };
const weakRef = new WeakRef(this);
const eventListener = () => {
console.log('eventListener called!');
strongRefs.finalizer = null;
weakRef.deref()?.test();
}
finalizer.register(this, { eventTarget, eventListener });
eventTarget.addEventListener('testEvent', eventListener, { once: true });
}
test() {
console.log("test called!");
}
}
async function main() {
const gc = globalThis?.global?.gc;
console.log(`garbage collector func: ${gc}`);
const eventTarget = new EventTarget();
for (let i = 10; i > 0; i--) {
void function () {
// these instances of Transient really must be getting GC'ed!
new Transient(eventTarget);
}();
await new Promise(r => setTimeout(() => r(gc?.(true)), 100));
}
console.log("finishing...")
gc?.(true);
await new Promise(r => setTimeout(r, 5000));
eventTarget.dispatchEvent(new Event("testEvent"));
console.log("done.")
}
main().catch(console.error);
更新了,如果我增加for循环集成的数量,我最终会看到一些finalizerCallback调用,但它们仍然是零星的。
https://stackoverflow.com/questions/65175380
复制相似问题