我想通过domain把截获的错误返回给客户端(下面的实现是模拟一个异步异常),第一次请求没有问题,但是第二次以后浏览器都会一直处于pending状态,我的理解是第二次请求使用了第一次请求domain里面的对像,也就是说B域访问了A域下面的变量,这样跨域访问数据导致第二次以后的请求拿到的response对像都是A域这个上下文中的,而第一次请求后response已经无效了,也就是说A域这个response没用了,每次都调用response.writeHead都是无效的。当一个进程中有公共变量的时候就会出现这样的问题,求解大神解决这个问题!!
var http = require('http'),
events = require('events');
domain = require('domain'),
net = require('net'),
util = require('util'),
shareObject = null;
function InheritEventObject()
{
events.EventEmitter.apply(this);
}
util.inherits(InheritEventObject, events.EventEmitter);
var cnt = 0;
http.createServer(function(request, response) {
var rdomain = domain.create();
rdomain.data = ++cnt;
rdomain.on('error', function(err) {
console.log(this.data);//每次都是1
response.writeHead(500);
response.end(err.stack);
});
rdomain.run(function(){
var obj = getShareObject();
obj.emit("throwError");
});
}).listen(8080);
function getShareObject()
{
if(shareObject === null)
{
shareObject = new InheritEventObject();
shareObject.on("throwError", function(){
throw new Error("hello error");
});
}
return shareObject;
}
function InheritEventObject()
{
// 删掉下面这一行就正常了,暂时没看是神马原因
// 但有一点可以肯定的是,你这种写法跟后面的util.inherits()是重复的
// events.EventEmitter.apply(this);
}
util.inherits(InheritEventObject, events.EventEmitter);
大概的原因是:
本来你想实现继承EventEmitter,直接执行util.inherits(InheritEventObject, events.EventEmitter);
即可,但是你又在InheritEventObject()
中执行了events.EventEmitter.apply(this);
,导致把当前的Domain对象绑定到了新创建的InheritEventObject对象上(其实你这种写法本来就是不对的)。以后在每次访问请求时,用的是同一个InheritEventObject对象,那么其出错的时候,也是触发同一个Domain对象的error事件,而里面的Response对象早已经关闭了,所以只要第一次请求能返回,后续的请求都没法返回出错信息。
而若在rdomain.on('error', function () {})
处理后,执行rdomain.dispose()
来销毁当前的Domain对象,则原来的InheritEventObject对象所绑定的Domain也失效,程序能正确找到当前真正的Domain,所以能正常运行:
rdomain.on('error', function(err) {
console.log(this.data);//每次都是1
response.writeHead(500);
response.end(err.stack);
rdomain.dispose();
});
EventEmitter的源码:
function EventEmitter() {
this.domain = null;
if (exports.usingDomains) {
// if there is an active domain, then attach to it.
domain = domain || require('domain');
if (domain.active && !(this instanceof domain.Domain)) {
this.domain = domain.active;
}
}
this._events = this._events || null;
this._maxListeners = this._maxListeners || defaultMaxListeners;
}