4

私はこれに似たものを持っています:

var domain = require ("domain");
var http = require ("http");

var d = domain.create ();
d.on ("error", function (error){
    console.error (error);
    //res.writeHead (500)
    //res.end ()
});
d.run (function (){
    http.createServer (function (req, res){
        null.error
    }).listen (1337, "localhost");
});

私のサーバーはすべてドメイン内で実行されます。リクエスト中にエラーが発生した場合、ユーザーに 500 エラーを送信したいのですが、エラー ハンドラ内ではレスポンス オブジェクトにアクセスできません。


私の最初の試みは、ドキュメントにあるように、リクエストごとに明示的なドメインを使用することです。

var d = domain.create ();
d.on ("error", function (error){
    //res.writeHead (500);
    //res.end ()
    console.error (error);
});
d.run (function (){
    http.createServer (function (req, res){
        var dreq = domain.create ();
        dreq.add (req)
        dreq.add (res)
        dreq.on ("error", function (error){
            res.writeHead (500);
            res.end ()
            console.error (error);
        });
        null.error
    }).listen (1337, "localhost");
});

dreqエラーハンドラーが呼び出されることはreqありません。なぜならres、エラーは実行時に発生し、出力されないためです。これは TypeError です。


2 番目の試みはres、イベント エミッターなどのクロージャーを使用してオブジェクトへの参照を保存することです。

var domain = require ("domain");
var http = require ("http");
var events = require ("events");

var emitter = new events.EventEmitter ();

var d = domain.create ();
d.on ("error", function (error){
    emitter.emit ("error", error);
});
d.run (function (){
    http.createServer (function (req, res){
        emitter.once ("error", function (error){
            res.writeHead (500);
            res.end ();
            console.error (error);
        });
        null.error
    }).listen (1337, "localhost");
});

これは機能し、エラーはエラー ハンドラーでキャッチされて出力されるため、応答オブジェクトを使用してユーザーにメッセージを送信できます。node.js の基本に関する知識がほとんどない場合は、この回避策が完全にバグであることがわかります。イベント ループに 5 つのユーザー リクエストがあり、そのうちの 1 つがエラーをスローするタスクを実行する場合、エミッターはすべてのエラー ハンドラーを実行し、5 人のユーザーのうち 1 人だけが 500 を受け取る必要がある場合に、500 エラーで通知されます。エラー。


私の最後の試みは、リクエストごとにサブコンテキストを作成することです。ドキュメントは、このパターンについて何も述べていません。これは私を少し混乱させます:

過度のメモリ使用を防ぐために、Domain オブジェクト自体はアクティブなドメインの子として暗黙的に追加されません。もしそうなら、リクエストとレスポンスオブジェクトが適切にガベージコレクションされないようにするのは簡単すぎるでしょう.

Domain オブジェクトを親 Domain の子としてネストする場合は、それらを明示的に追加し、後で破棄する必要があります。

var domain = require ("domain");
var http = require ("http");

var d = domain.create ();
d.on ("error", function (error){
    console.error (error);
});
d.run (function (){
    http.createServer (function (req, res){
        var dreq = domain.create ();
        dreq.on ("error", function (error){
            res.writeHead (500);
            res.end ()
            console.error (error);
            dreq.dispose ();
        });
        dreq.run (function (){
            null.error
            //...
            //dreq.dispose ();
        });
    }).listen (1337, "localhost");
});

メモリリークが発生していますか?


簡単な解決策は、各リクエストに一意の ID を割り当て、それらをオブジェクトまたは配列に保存し、エミッターが発行するときに、一意の ID を指定して実行する必要があるハンドラーを見つけることです。まったく受け入れられません。


オブジェクトへの参照を保存できない場合res、ドメイン エラー ハンドラ内でユーザーにエラーを送信するにはどうすればよいですか?

4

3 に答える 3

1

このソリューションが勝者です。

var domain = require ("domain");
var http = require ("http");

var d = domain.create ();
d.on ("error", function (error){
    console.error (error);
});
d.run (function (){
    http.createServer (function (req, res){
        var dreq = domain.create ();
        dreq.add (req);
        dreq.add (res);
        dreq.on ("error", function (error){
            res.on ("close", function (){
                dreq.exit ();
            });
            res.writeHead (500);
            res.end ()
            console.error (error);
            dreq.exit();
        });
        dreq.run (function (){
            null.error
        });
    }).listen (1337, "localhost");
});

https://github.com/joyent/node/issues/4905

于 2013-03-04T10:21:41.313 に答える
0

あなたが最後に投稿した解決策は、実際にあなたがすべきことです。これは、ドキュメントが推奨するネストのタイプと同じではありません。あなたがしているのは、ドメイン内の潜在的に(またはこの場合は間違いなく)エラーのあるコードをラップして、エラーが発生したときにドメインによって処理されるようにすることだけです。

于 2013-03-03T07:41:14.323 に答える
0

このソリューションは私にとってはうまくいきます:

var http = require('http');
var domain = require('domain');

var server = http.createServer (function (req, res) {
    var reqDomain = domain.create();
    reqDomain.on('error', function (error) {
        res.writeHead(500);
        res.end('error 500');
        console.error(error);
    });
    res.on('close', function () {
        reqDomain.dispose();
    });
    reqDomain.run(function () {
        // Request handler code here
        null.error
    });
}).listen(3000);

server.on('error', function (error) {
    console.error('Server error: ' + error);
});
于 2013-03-03T07:48:34.983 に答える