2011-09-08 4 views
17

Я делаю длинный опрос с node.js.
В основном сервер node.js принимает запрос от пользователя и затем проверяет наличие некоторых обновлений. Если обновлений нет, они будут проверять их после таймаута.
Но что, если пользователь закрыл свою вкладку или перешел на другую страницу? В моем случае сценарий продолжает работать.
Есть ли способ в node.js проверить или обнаружить или поймать событие, когда пользователь прервал его запрос (закрыл соединение)?Как проверить, было ли соединение прервано на сервере node.js

ответ

17

Благодаря и ответы Miroshko в yojimbo87, я был в состоянии поймать «закрыть» событие, но я должен был сделать несколько дополнительных настроек.

Причина, по которой просто ловить «закрытие» события не устраняет мою проблему, заключается в том, что когда клиент отправляет запрос на сервер 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); 

Мой исходный код намного больше, так что мне пришлось сократить его много раз, чтобы показать чувствительные части.

Я хотел бы знать, есть ли лучшие решения, но это работает на меня сейчас.

4

Есть ли способ в Node.js для проверки или обнаружения или поймать событие, когда пользователь прервал его запрос (закрыл соединение)?

Вы можете использовать http.ServerRequest close event. Простой пример:

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

Вы должны использовать 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) 
    ... 
2

Я использую Express.js (~ 4.10.6) и следующий код работает отлично для меня: Как только

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

когда я закрываю вкладку браузера, браузер закрывает соединение, и функция обратного вызова запускается, как и ожидалось.

+0

На этой странице появилось больше информации о обнаружении закрытых TCP-соединений в целом: http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html –

Смежные вопросы