假设我有一个简单的http服务器,例如:
var http = require('http');
http.createServer(function (req, res) {
req.on('data', function (data) {
console.log('Got some data: ' + data);
});
req.on('end', function () {
console.log('Request ended!');
});
res.end('Hello world!');
}).listen(3000);
所以,基本上是默认的101样本,到目前为止没什么特别的 - 除了我订阅可读data
流的end
和req
事件。现在我想知道当我不再需要它们时是否必须取消订阅这些事件?
或者当可读流结束时它们会自动清除吗?
这样的代码会导致内存泄漏吗?
答案 0 :(得分:15)
(这个答案包含指向node.js源代码的重要部分的链接)
在回答你的问题之前,让我们谈谈事件。当你这样做时:
emitter.on('an-event', listener);
listener
被添加到emitter
附加的list。稍后,当emitter
触发事件时,它会通过迭代列表来通知所有订阅该事件的侦听器。 node.js事件发射器的神奇之处在于您不会自己声明或管理该列表。
但是,每当您致电.on()
时,您都会创建一个back-reference发射器 - >监听器。如果您从未取消订阅,此引用将阻止GC收集侦听器并创建“泄漏”。
这通常不会经常发生在node.js上,因为通常情况下,发射器会在侦听器之前被销毁,但实际发生这种情况的情况是当你有一个长时间运行的连接(想想Twitter Streaming API)时有时会重新连接。如果您不注销事件,则可能会从旧连接获取事件并认为它们适用于新连接。这可能会让您认为新连接已关闭。
node.js会在认为您可能忘记取消注册侦听器时打印臭名昭着的"possible leak detected"消息。
回到你的例子:
这不会造成泄漏,因为套接字(req + res)将首先被销毁。由于它是发射器,node.js将forcibly remove all listeners。