Как проверить, было ли прервано соединение на сервере node.js - PullRequest
23 голосов
/ 08 сентября 2011

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

Ответы [ 5 ]

24 голосов
/ 08 марта 2014

Вам нужно использовать 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)
  ...
18 голосов
/ 09 сентября 2011

Благодаря ответам Мирошко и yojimbo87 я смог поймать событие 'close', но мне пришлось внести некоторые дополнительные изменения.Причина, по которой просто перехват события '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);

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

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

4 голосов
/ 08 сентября 2011

Есть ли способ в 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");
3 голосов
/ 24 декабря 2014

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

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

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

3 голосов
/ 08 сентября 2011

Похоже, ваш вопрос очень похож на этот:

Событие закрытия соединения HTTP-запроса NodeJS сработало дважды

1007 * попробовать *

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