Существует, по-видимому, известная проблема с прикреплением обработчиков событий после того, как событие уже создано. Это проблема, в основном, при вызове функции, которые следуют образцу возвращающего 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);
});
Это возвратит необработанное исключение ошибок, потому что в то время error
испускаются, ни одного обработчика для этого не еще прилагаются :
[email protected]:~$ 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 \t doSomethingAsync(ev) {
\t var something = null;
\t // Caller will never see this event because its
\t // handler is bound after fact.
\t if(!something) {
\t \t ev.emit('error', 'Something is null!');
\t }
};
var res = new EventEmitter();
res.on('error', function(s) {
\t console.log('Error returned: ' + s);
});
doSomethingAsync(res);
Это кажется безвкусным и грязным, хотя. Единственная причина, по которой обработчики событий в асинхронных операциях, которые применяются при первом методе, работает вообще, состоит в том, что для рассматриваемых операций обычно требуется больше времени, чем функция возвращает. Это дает время вызова для применения обработчиков событий к возвращенному EventEmitter
.
Наверняка есть предпочтительный шаблон, идиома или скрытый бит функции JavaScript или узла, чтобы лучше обрабатывать этот случай?
Я полагаю, что один подход заключается в том, чтобы не использовать EventEmitters
для передачи ошибок проверки или других ошибок, которые могут произойти мгновенно, но просто вернуть что-то еще. Но я все еще думаю, что это не решение основной проблемы; эта модель, широко представленная в документации Node и в другом месте, основывается на предположении, что операция async займет больше времени, чем время, необходимое для привязки обработчиков событий после возврата EventEmitter
. В большинстве случаев это, вероятно, так, но не может быть гарантировано.
Вот почему я думаю, что должен быть лучший способ. Если этого не произойдет, это сделало бы документацию Node о наилучшем практическом использовании EventEmitters
очень вводящим в заблуждение. Наверняка есть лучший способ?
То, что я полагаю, было бы идеально, чтобы иметь очереди EventEmitter испускаемые события, пока слушатель для них не связан, и только испускают их тогда. –