Я делаю длинный опрос с помощью node.js.
В принципе, сервер node.js принимает запрос от пользователя и затем проверяет наличие некоторых обновлений. Если обновлений нет, они будут проверять их после таймаута.
Но что, если пользователь закрыл свою вкладку или перешел на другую страницу? В моем случае, script продолжает работать.
Есть ли способ в node.js проверить или обнаружить или поймать событие, когда пользователь прервал его запрос (закрыл соединение)?
Как проверить, было ли соединение прервано на сервере node.js
Ответ 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");
Ответ 4
Кажется, что ваш вопрос очень похож на этот:
Дважды запущено событие соединения NodeJS HTTP-запроса
попробовать
request.connection.on('close', function () {
...
});
Ответ 5
Я использую Express.js(~ 4.10.6), и следующий код работает отлично для меня:
//GET Request:
app.get('/', function(req, res){
req.on('close', function(){
console.log('Client closed the connection');
});
});
Как только я закрою вкладку браузера, браузер закроет соединение, и функция обратного вызова будет выполнена, как ожидалось.