我在Stackoverflow上看到过回答提到,如果一个DOM元素超出作用域,它的事件监听器会被自动垃圾回收。那么,非DOM元素(例如EventSource)是否也是如此呢?
这里有一个示例:
function checkStatus(events) {
return function() {
if (events.readyState === EventSource.CLOSED) {
establishSSE(); // Is this fine?
} else {
setTimeout(checkStatus(events), 500);
}
}
}
function establishSSE() {
const events = new EventSource("/sse/" + sseID);
events.addEventListener("reply", sseReply);
events.addEventListener("refresh", sseRefresh);
setTimeout(checkStatus(events), 500);
}
establishSSE();
(我知道可以使用 onerror
事件。这只是一个例子)
在这种情况下,当第4行重新运行 establishSSE
时,之前的事件处理程序会被垃圾回收吗?
编辑:
我不明白这些值如何被垃圾回收。例如,以下代码可行:
function sseSubscribe() {
let events = new EventSource("/v1/sse/mySSEID");
events.addEventListener("message", sseHeartbeat);
events.addEventListener("reply", sseReply);
}
也就是说,新消息仍会导致message
和reply
处理程序运行。
但是events
在程序中再也无法访问。那么,它不应该已经被垃圾回收了吗?看起来EventSource
从未被垃圾回收(除非连接断开?)
编辑#2:
看起来即使事件处理程序是匿名的,如下所示:
function sseSubscribe() {
let events = new EventSource("/v1/sse/SSEID");
events.addEventListener("message", function() {
console.log("Heartbeat");
});
}
sseSubscribe();
在我的端上还是可以工作的。也就是说,Heartbeat
每30秒(服务器发送的间隔)会被记录在控制台中。尽管events
立即超出范围并且在程序的任何其他地方都无法访问,但仍然是如此。
EventSource
上的close
不会标记该对象可供垃圾回收。https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/eventsource/event_source.cc;l=209;bpv=0;bpt=0 - Ryan Peschel