我正在用 node.js 进行一些长时间的轮询。
基本上,node.js 服务器接受来自用户的请求,然后检查一些更新。如果没有更新,它将在超时后检查它们。
但是如果用户关闭了他的标签,或者转到另一个页面怎么办?就我而言,脚本继续工作。
当用户中止他的请求(关闭连接)时,node.js 中有没有办法检查或检测或捕捉事件?
5 回答
您需要使用req.on('close', function(err) { ... });
而不是req.connection.on('close', function(err) { ... });
有一个非常重要的区别。req.on() 为这个请求添加了一个监听器,而 req.connection.on() 则为客户端和服务器之间的(keep-alive)连接添加了一个监听器。如果你使用 req.connection.on(),每次客户端重用一个连接时,你都会为同一个连接增加一个监听器。当连接最终中止时,所有侦听器都会被触发。
函数作用域通常可以让你避免搞砸你的服务器逻辑,但这仍然是一件危险的事情。幸运的是,至少 NodeJS 0.10.26 足够聪明,可以警告用户:
(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace:
at Socket.EventEmitter.addListener (events.js:160:15)
at Socket.Readable.on (_stream_readable.js:689:33)
...
感谢Miroshko和yojimbo87 的回答,我能够捕捉到“关闭”事件,但我必须进行一些额外的调整。
仅捕获“关闭”事件并不能解决我的问题的原因是,当客户端将请求发送到 node.js 服务器时,如果连接仍处于打开状态,则服务器本身无法获取信息,直到他将某些内容发送回客户端(据我了解 - 这是因为 HTTP 协议)。
因此,额外的调整是不时向响应中写入一些内容。
阻止此工作的另一件事是,我将“内容类型”设置为“应用程序/json”。将其更改为“文本/javascript”有助于流式传输“空白”
最后,我有这样的事情:
var server = http.createServer(function(req,res){
res.writeHead(200, {'Content-type': 'text/javascript'});
req.connection.on('close',function(){
// code to handle connection abort
});
/**
* Here goes some long polling handler
* that performs res.write(' '); from time to time
*/
// some another code...
});
server.listen(NODE_PORT, NODE_LISTEN_HOST);
我的原始代码要大得多,所以我不得不削减很多只是为了显示敏感部分。
我想知道是否有更好的解决方案,但这目前对我有用。
当用户中止他的请求(关闭连接)时,node.js 中有没有办法检查或检测或捕捉事件?
您可以尝试使用http.ServerRequest 关闭事件。简单的例子:
var http = require("http"),
util = require("util");
var httpServer = http.createServer(function(req, res) {
util.log("new request...");
// notify me when client connection is lost
req.on("close", function(err) {
util.log("request closed...");
});
// wait with response for 15 seconds
setTimeout(function() {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write("response");
res.end();
util.log("response sent...");
}, 15000);
});
httpServer.listen(8080);
util.log("Running on 8080");
我正在使用 Express.js (~4.10.6),以下代码对我来说工作正常:
//GET Request:
app.get('/', function(req, res){
req.on('close', function(){
console.log('Client closed the connection');
});
});
一旦我关闭浏览器的选项卡,浏览器就会关闭连接,并且回调函数会按预期执行。