我正在使用 Node.js 进行一些长轮询。
基本上,node.js 服务器接受用户的请求,然后检查一些更新。如果没有更新,它将在超时后检查它们。
但是,如果用户关闭了标签页或转到了另一个页面怎么办?就我而言,脚本继续工作。
当用户中止请求(关闭连接)时,node.js 有没有办法检查或检测或捕获事件?
您需要使用
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
事件。
感谢 Miroshko's 和 yojimbo87'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);
我的原始代码要大得多,所以我必须对其进行大量剪切才能显示敏感部分。
我想知道是否有更好的解决方案,但这目前对我有用。
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');
});
});
一旦我关闭浏览器的选项卡,浏览器就会关闭连接,回调函数就会按预期执行。