2011-09-08 4 views
17

Estoy haciendo una larga encuesta con node.js.
Básicamente, el servidor node.js acepta la solicitud del usuario y luego verifica algunas actualizaciones. Si no hay actualizaciones, las comprobará después del tiempo de espera.
Pero, ¿qué sucede si el usuario ha cerrado su pestaña o ha ido a otra página? En mi caso, el script continúa funcionando.
¿Hay alguna manera en node.js de verificar o detectar o atrapar un evento cuando el usuario ha abortado su solicitud (cerró la conexión)?Cómo comprobar si la conexión se anuló en el servidor node.js

Respuesta

17

Gracias a y respuestas de yojimbo87 de Miroshko que fue capaz de capturar el evento 'cerca', pero tuvieron que hacer algunos ajustes adicionales.

La razón por la cual el evento capturar 'cerrar' no solucionaba mi problema, es que cuando el cliente envía la solicitud al servidor node.js, el servidor no puede obtener información si la conexión sigue abierta hasta que le devuelve algo al cliente (por lo que yo entiendo, esto se debe al protocolo HTTP).
Por lo tanto, el ajuste adicional era escribir algo a la respuesta de vez en cuando.
Una cosa más que impedía que esto funcionara, es que tenía 'Content-type' como 'application/json'. Cambiarlo a 'texto/javascript' ayudó a transmitir 'espacios en blanco' de vez en cuando sin cerrar la conexión.
Al final, he tenido algo como esto:

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

Mi código original es mucho más grande, así que tuve que cortarlo mucho sólo para mostrar las partes sensibles.

Me gustaría saber si hay mejores soluciones, pero esto está funcionando para mí en este momento.

4

¿Hay una manera de Node.js para comprobar o detectar o para coger un evento cuando el usuario ha abortado su solicitud (cerró la conexión)?

Puede intentar usar http.ServerRequest close event. Un simple ejemplo:

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

Es necesario utilizar req.on('close', function(err) { ... }); en lugar de req.connection.on('close', function(err) { ... });

Hay una distinción muy importante. req.on() agrega un oyente a esta solicitud mientras que req.connection.on(), agrega un oyente a la conexión (keep-alive) entre el cliente y el servidor. Si usa req.connection.on(), cada vez que el cliente vuelve a utilizar una conexión, agrega un oyente más a la misma conexión. Cuando finalmente se interrumpe la conexión, todos los oyentes son despedidos.

La definición del alcance de las funciones normalmente lo mantiene a salvo de este error de la lógica de su servidor, pero, sin embargo, es algo peligroso. Afortunadamente al menos NodeJS 0.10.26 es lo suficientemente inteligente como para advertir al usuario de este:

(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) 
    ... 
2

estoy usando Express.js (~ 4.10.6) y el siguiente código está trabajando muy bien para mí:

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

Tan pronto cuando cierro la pestaña del navegador, el navegador cierra la conexión y la función de devolución de llamada se ejecuta como se esperaba.

+0

Esta página tiene más información sobre la detección de conexiones TCP cerradas en general: http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html –

Cuestiones relacionadas