我有类似的东西:
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。
我的第二次尝试是使用闭包来保存对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个执行抛出错误的任务,则发射器将执行所有错误处理程序,并且当只有1个用户应该收到500个错误时,将通知500个用户500个错误错误。
我的最后一次尝试是为每个请求创建子上下文。文档没有说明这种模式。这对我来说有点混乱:
为了防止过多的内存使用,域对象本身不会隐式添加为活动域的子项。如果是这样的话,那么防止请求和响应对象被正确地进行垃圾收集就太容易了。
如果要将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
对象的引用,如何向域错误处理程序内的用户发送错误?
答案 0 :(得分: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");
});
答案 1 :(得分:0)
你上次发布的解决方案实际上是你应该做的。这与文档建议的嵌套类型不同。你正在做的就是在域中包装潜在的(或者,在这种情况下,肯定的)错误代码,这样当它发出由域处理的错误时。
答案 2 :(得分: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);
});