Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

Благодаря ответам 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);

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

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

Ответ 2

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

Ответ 3

Есть ли способ в 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");

Ответ 5

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

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

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