【发布时间】:2020-09-06 20:43:44
【问题描述】:
在已经生成事件之后附加事件处理程序有一个看似众所周知的问题。这主要是在调用遵循返回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);
});
这将返回一个未处理的错误异常,因为在发出 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)
我能想到的唯一解决方案是在调用端创建一个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);
不过,这似乎不雅且凌乱。通过第一种方法应用的异步操作上的事件处理程序完全起作用的唯一原因是,所讨论的操作通常需要比函数返回更长的时间才能完成。这让调用者有时间将事件处理程序应用于返回的EventEmitter。
肯定有首选的模式、习语或 JavaScript 或 Node 功能的隐藏位来更好地处理这种情况?
我想一种方法是不使用EventEmitters 传输验证错误或其他可能立即发生的错误,而只是返回其他内容。但我仍然认为这不是解决本质问题的方法。这个模型在 Node 文档和其他地方广泛描述,它依赖于这样一个假设,即异步操作完成所需的时间比返回 EventEmitter 后绑定事件处理程序所需的时间要长。大多数时候,这可能是真的,但不能保证它是真的。
这就是为什么我认为必须有更好的方法。如果没有,那将使有关EventEmitters 的最佳实用使用的 Node 文档非常具有误导性。肯定有更好的方法吗?
【问题讨论】:
-
我认为理想的做法是让 EventEmitter 队列发射事件,直到它们的监听器被绑定,然后才发射它们。
标签: javascript node.js eventemitter