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

vfh0ocws  于 2023-10-17  发布在  Node.js
关注(0)|答案(6)|浏览(191)

我用node.js做了一个长时间的投票。
基本上,node.js服务器接受来自用户的请求,然后检查一些更新。如果没有更新,它将在超时后检查它们。
但是,如果用户关闭了他的标签页,或转到另一个页面呢?在我的情况下,脚本继续工作。
在node.js中是否有一种方法来检查或检测或捕获用户放弃请求(关闭连接)时的事件?

gtlvzcf8

gtlvzcf81#

您需要使用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)
  ...

**编辑:抬头!**正如@Matt在评论中提到的,解析body会触发request'close'事件,即使响应还没有完成流回客户端。使用res.on('close', ...)代替。

qeeaahzv

qeeaahzv2#

多亏了 *Miroshko * 和 * yojimbo 87 * 的回答,我才能捕捉到“关闭”事件,但我不得不做一些额外的调整。
仅仅捕获'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);

我的原始代码要大得多,所以我不得不削减了很多,只是为了显示敏感的部分。
我想知道是否有更好的解决方案,但这对我来说是工作的时刻。

wfauudbj

wfauudbj3#

在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");
50pmv0ei

50pmv0ei4#

你的问题似乎和这个很相似:
NodeJS HTTP request connection's close event fired twice
尝试

request.connection.on('close', function () {
  ... 
});
33qvvth1

33qvvth15#

我使用的是js.js(~4.10.6),下面的代码对我来说工作得很好:

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

只要我关闭浏览器的标签,浏览器就会关闭连接,回调函数就会按预期执行。

yeotifhr

yeotifhr6#

从节点16开始,如果你想检测一个中止信号(如果你的客户端使用了一个fetch AbortController),你可以用途:

req.socket.on('close', () => {    
 //...
});

看看这个thread:Client aborts does not trigger "close" event on Node.js request in Node 16指出了这个问题:https://github.com/nodejs/node/issues/38924

相关问题