26

node.js で長いポーリングを行っています。
基本的に、node.js サーバーはユーザーからのリクエストを受け入れ、いくつかの更新をチェックします。更新がない場合は、タイムアウト後にチェックします。
しかし、ユーザーが自分のタブを閉じたり、別のページに移動したりした場合はどうなるでしょうか? 私の場合、スクリプトは引き続き機能します。
ユーザーがリクエストを中止した (接続を閉じた) ときに、node.js でイベントをチェック、検出、またはキャッチする方法はありますか?

4

5 に答える 5

27

req.on('close', function(err) { ... });代わりに使用する必要がありますreq.connection.on('close', function(err) { ... });

非常に重要な違いがあります。req.on() はこのリクエストにリスナーを追加しますが、req.connection.on() はクライアントとサーバー間の (キープアライブ) 接続にリスナーを追加します。req.connection.on() を使用すると、クライアントが接続を再利用するたびに、同じ接続にもう 1 つのリスナーが追加されます。接続が最終的に中止されると、すべてのリスナーが起動されます。

通常、関数のスコープを設定すると、サーバー ロジックが台無しになるのを防ぐことができますが、それでも危険です。幸いなことに、少なくとも 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)
  ...
于 2014-03-08T14:06:52.083 に答える
19

Miroshkoyojimbo87の回答のおかげで、「閉じる」イベントをキャッチすることができましたが、さらに調整を加える必要がありました。

「close」イベントをキャッチしただけでは問題が解決しなかった理由は、クライアントがnode.jsサーバーにリクエストを送信するときに、接続がまだ開いている場合、サーバー自体が何かを送り返すまで情報を取得できないためです。クライアント(私が理解している限り、これはHTTPプロトコルによるものです)。
したがって、追加の調整は、時々応答に何かを書き込むことでした。
これが機能するのを妨げていたもう1つのことは、「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);

私の元のコードははるかに大きいので、敏感な部分を表示するためだけにそれをたくさんカットしなければなりませんでした。

より良い解決策があるかどうか知りたいのですが、これは現在私のために働いています。

于 2011-09-09T11:30:17.597 に答える
4

ユーザーがリクエストを中止した (接続を閉じた) ときに、node.js でイベントをチェック、検出、またはキャッチする方法はありますか?

http.ServerRequest close eventを使用してみることができます。簡単な例:

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");
于 2011-09-08T18:03:55.953 に答える
4

私は Express.js (~4.10.6) を使用していますが、次のコードは問題なく動作しています:

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

ブラウザーのタブを閉じるとすぐに、ブラウザーは接続を閉じ、コールバック関数が期待どおりに実行されます。

于 2014-12-24T06:28:19.763 に答える
3

あなたの質問はこれと非常に似ているようです:

NodeJSHTTPリクエスト接続のcloseイベントが2回発生しました

試す

request.connection.on('close', function () {
  ... 
}); 
于 2011-09-08T16:30:57.140 に答える