Как проверить, было ли соединение прервано на сервере node.js

17

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

    
задан WallTearer 08.09.2011 в 15:21
источник

5 ответов

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

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

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

    
ответ дан WallTearer 09.09.2011 в 13:30
источник
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)
  ...
    
ответ дан Sampo Savolainen 08.03.2014 в 15:06
источник
4
  

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

Вы можете попытаться использовать ссылку . Простой пример:

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");
    
ответ дан yojimbo87 08.09.2011 в 20:03
источник
2

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

дважды запущено событие соединения NodeJS HTTP

попробовать

request.connection.on('close', function () {
  ... 
}); 
    
ответ дан Miroshko 08.09.2011 в 18:30
источник
2

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

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

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

    
ответ дан Shivanshu Goyal 24.12.2014 в 07:28
источник
  • На этой странице содержится больше информации об обнаружении закрытых TCP-соединений в целом: blog.stephencleary.com/2009/05/... –  Shivanshu Goyal 24.12.2014 в 07:43