如何检查node.js服务器中的连接是否中止

问题描述 投票:0回答:5

我正在使用 Node.js 进行一些长轮询。
基本上,node.js 服务器接受用户的请求,然后检查一些更新。如果没有更新,它将在超时后检查它们。
但是,如果用户关闭了标签页或转到了另一个页面怎么办?就我而言,脚本继续工作。
当用户中止请求(关闭连接)时,node.js 有没有办法检查或检测或捕获事件?

node.js connection request abort
5个回答
27
投票

您需要使用

req.on('close', function(err) { ... });
而不是
req.connection.on('close', function(err) { ... });

有一个非常重要的区别。 req.on() 向该请求添加一个监听器,而 req.connection.on() 则向客户端和服务器之间的(保持活动)连接添加一个监听器。如果您使用 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)
  ...

编辑:注意! 正如 @Matt 在评论中提到的,如果您正在解析

res.on('close', ...);
请求的 body,则应该使用 POST (即
response
而不是
request
),因为即使响应尚未完成流回客户端,解析
body
也会触发
'close'
request
事件。


19
投票

感谢 Miroshko'syojimbo87's 的回答,我能够捕捉到“关闭”事件,但我必须进行一些额外的调整。

仅仅捕获“close”事件并不能解决我的问题的原因是,当客户端将请求发送到node.js服务器时,如果连接仍然打开,服务器本身无法获取信息,直到他将某些内容发送回客户端(据我了解 - 这是因为 HTTP 协议)。
因此,额外的调整是不时在响应中写入一些内容。
阻止此工作的另一件事是我将“Content-type”设置为“application/json”。将其更改为“text/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);

我的原始代码要大得多,所以我必须对其进行大量剪切才能显示敏感部分。

我想知道是否有更好的解决方案,但这目前对我有用。


5
投票

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");

4
投票

我正在使用 Express.js (~4.10.6),以下代码对我来说运行良好:

//GET Request:
app.get('/', function(req, res){
    req.on('close', function(){
        console.log('Client closed the connection');
    });
});

一旦我关闭浏览器的选项卡,浏览器就会关闭连接,回调函数就会按预期执行。


3
投票

看来你的问题和这个很相似:

NodeJS HTTP 请求连接的关闭事件触发了两次

尝试

request.connection.on('close', function () {
  ... 
}); 
© www.soinside.com 2019 - 2024. All rights reserved.