EventEmitter事件处理程序的延期附件模式?

在事件已经生成之后,附加事件处理程序有一个看似众所周知的问题。 主要是在调用返回EventEmitter模式的函数时,这是一个问题,例如:

 var EventEmitter = require('events').EventEmitter; function doSomethingAsync() { var ev = new EventEmitter(), something = null; // Caller will never see this event because its // handler is bound after fact. if(!something) { ev.emit('error', 'Something is null!'); return ev; } return ev; } var res = doSomethingAsync(); res.on('error', function(s) { console.log('Error returned: ' + s); }); 

这将返回一个未处理的错误exception,因为在发生error的时候,还没有处理它:

 sasha@peacock:~$ node test.js events.js:87 throw Error('Uncaught, unspecified "error" event.'); ^ Error: Uncaught, unspecified "error" event. at Error (native) at EventEmitter.emit (events.js:87:13) at doSomethingAsync (/home/sasha/test.js:11:6) at Object.<anonymous> (/home/sasha/test.js:18:11) at Module._compile (module.js:460:26) at Object.Module._extensions..js (module.js:478:10) at Module.load (module.js:355:32) at Function.Module._load (module.js:310:12) at Function.Module.runMain (module.js:501:10) at startup (node.js:124:16) 

我所能想到的唯一解决scheme是在调用端创build一个EventEmitter ,事先绑定处理程序,并将其传递给函数:

 var EventEmitter = require('events').EventEmitter; function doSomethingAsync(ev) { var something = null; // Caller will never see this event because its // handler is bound after fact. if(!something) { ev.emit('error', 'Something is null!'); } }; var res = new EventEmitter(); res.on('error', function(s) { console.log('Error returned: ' + s); }); doSomethingAsync(res); 

虽然这看起来不雅观和凌乱。 通过第一种方法应用于asynchronous操作的事件处理程序的唯一原因是因为所讨论的操作通常需要较长时间才能完成,而不是函数返回。 这给了调用者时间将事件处理程序应用到返回的EventEmitter

当然,有一个首选的模式,成语,或隐藏的JavaScript或节点的function,以更好地处理这种情况?

我想一种方法是不使用EventEmitters传输validation错误或其他可能发生的瞬间错误,但只是返回别的东西。 但我仍然认为这不是解决基本问题的方法; 在Node文档和其他地方广泛描述的这个模型依赖于这样的假设:asynchronous操作的完成时间EventEmitter返回EventEmitter之后绑定事件处理程序所花费的时间要长。 大多数情况下,这可能是真实的,但不能保证是真实的。

这就是为什么我认为一定有更好的办法。 如果没有,这将使Node的文档对事件发送器的最佳实际使用非常误导。 当然有更好的方法?

您可以使用process.nextTick来延迟执行当前调用堆栈之后发生的事件。 举个例子:

 var EventEmitter = require('events').EventEmitter; function doSomethingAsync() { var ev = new EventEmitter(), something = null; // Caller will see this event because it // will be emitted after current call stack if(!something) { process.nextTick(function() { ev.emit('error', 'Something is null!'); }); return ev; } return ev; } var res = doSomethingAsync(); res.on('error', function(s) { console.log('Error returned: ' + s); });