2011-09-08 18 views
17

Robię długiej ankietę za pomocą node.js.
Zasadniczo serwer node.js przyjmuje żądanie od użytkownika, a następnie sprawdza niektóre aktualizacje. Jeśli nie ma żadnych aktualizacji, sprawdzi je po przekroczeniu limitu czasu.
Ale co, jeśli użytkownik zamknął swoją kartę lub przeszedł do innej strony? W moim przypadku skrypt nadal działa.
Czy jest jakiś sposób w pliku node.js, aby sprawdzić lub wykryć lub złapać zdarzenie, gdy użytkownik przerwał swoje żądanie (zamknął połączenie)?Jak sprawdzić, czy połączenie zostało przerwane na serwerze node.js

Odpowiedz

17

Dzięki Miroshko za i yojimbo87 za odpowiedzi udało mi się złapać „bliskie” zdarzenie, ale musiałem zrobić kilka dodatkowych usprawnień.

Powodem, dla którego samo uchwycenie zdarzenia "zamknięcie" nie rozwiązało problemu, jest to, że gdy klient wysyła żądanie do serwera node.js, sam serwer nie może uzyskać informacji, jeśli połączenie jest nadal otwarte, dopóki wysyła coś z powrotem do klienta (o ile zrozumiałem - wynika to z protokołu HTTP).
Tak więc dodatkową zmianą było od czasu do czasu napisanie czegoś do odpowiedzi.
Jeszcze jedną rzeczą, która uniemożliwiła to działanie, jest to, że miałem "Content-type" jako "application/json". Zmiana na "text/javascript" pomogła w streamowaniu "białych przestrzeni" od czasu do czasu bez zamykania połączenia.
W końcu miałem coś takiego:

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

Mój oryginalny kod jest znacznie większy, więc musiałem go wyciąć wiele prostu pokazać wrażliwych części.

Chciałbym wiedzieć, czy istnieją lepsze rozwiązania, ale teraz to działa dla mnie.

4

Czy istnieje sposób w node.js sprawdzić lub wykryć lub złapać zdarzenie, gdy użytkownik przerwał swoją prośbę (zamknął połączenie)?

Możesz spróbować użyć http.ServerRequest close event. Prosty przykład:

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

Trzeba użyć req.on('close', function(err) { ... }); zamiast req.connection.on('close', function(err) { ... });

Jest to bardzo ważne rozróżnienie. req.on() dodaje detektora do tego żądania, podczas gdy req.connection.on(), dodaje detektor do połączenia (keep-alive) między klientem a serwerem. Jeśli używasz komendy req.connection.on(), za każdym razem, gdy klient ponownie używa połączenia, dodajesz jeszcze jednego detektora do tego samego połączenia. Kiedy połączenie zostanie ostatecznie przerwane, wszyscy słuchacze zostają zwolnieni.

Scoping funkcji zwykle chroni przed tym, że wkręca się logika serwera, ale mimo to jest to niebezpieczne. Na szczęście przynajmniej NodeJS 0.10.26 jest na tyle silny, aby ostrzec użytkownika o tym:

(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

Używam Express.js (~ 4.10.6) i następujący kod działa dobrze dla mnie:

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

Niezwłocznie po zamknięciu karty przeglądarki przeglądarka zamyka połączenie, a funkcja wywołania zwrotnego zostaje wykonana zgodnie z oczekiwaniami.

+0

Ta strona zawiera więcej informacji na temat wykrywania zamkniętych połączeń TCP w ogóle: http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html –

Powiązane problemy