26

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

4

5 回答 5

27

您需要使用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)
  ...
于 2014-03-08T14:06:52.083 回答
19

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

仅捕获“关闭”事件并不能解决我的问题的原因是,当客户端将请求发送到 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);

我的原始代码要大得多,所以我不得不削减很多只是为了显示敏感部分。

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

于 2011-09-09T11:30:17.597 回答
4

当用户中止他的请求(关闭连接)时,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");
于 2011-09-08T18:03:55.953 回答
4

我正在使用 Express.js (~4.10.6),以下代码对我来说工作正常:

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

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

于 2014-12-24T06:28:19.763 回答
3

似乎您的问题与此问题非常相似:

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

尝试

request.connection.on('close', function () {
  ... 
}); 
于 2011-09-08T16:30:57.140 回答