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

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

5 ответов


вам нужно использовать req.on('close', function(err) { ... }); вместо req.connection.on('close', function(err) { ... });

существует очень важное различие. запрос.on () добавляет прослушиватель к этому запросу во время req.соединение.на () вы добавляете прослушиватель к (keep-alive) соединению между клиентом и сервером. Если вы используете Треб.соединение.на () каждый раз, когда клиент повторно использует соединение, вы добавляете еще один слушатель в той же связи. Когда соединение, наконец, прервано, все слушатели будут уволены.

функция scoping типично держит вас в безопасности от этого испортить логику сервера, но это опасная вещь, тем не менее. К счастью, по крайней мере 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)
  ...

спасибо Miroshko это и yojimbo87 это ответы я смог поймать событие "закрыть", но мне пришлось сделать некоторые дополнительные настройки.

Почему только "закрыть" событие не чинил моя проблема заключается в том, что когда клиент отправляет запрос к узлу.JS server, сам сервер не может получить информацию, если соединение все еще открыто, пока он не отправит что-то обратно клиенту (насколько я понял - это из-за HTTP протокол.)
Таким образом, дополнительная настройка заключалась в том, чтобы время от времени писать что-то в ответ.
Еще одна вещь, которая мешала этому работать, заключается в том, что у меня был "Content-type" как "application/json". Изменение его на "текст / 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);

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

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


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

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

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

попробовать

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

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

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

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