Потенциальная блокировка цикла событий в Node.js через EventEmitter - PullRequest
0 голосов
/ 05 января 2012

Предположим, следующий сценарий:

//Where "e" is a global object in the app  
e = new EventEmitter;  

...  

//at some place in the app code I'm adding Listener 1
e.on('myEvent', function() {console.log('Listener 1)});  

...  

//at another place in the app code I'm adding Listener 2
e.on('myEvent', function() {console.log('Listener 2)});  

...  

//at another place in the app code I'm adding Listener N
e.on('myEvent', function() {console.log('Listener N)});  

...  

//finally in some place I'm emitting "myEvent"
e.emit('myEvent', p1, p2);  

В тот момент, когда выполняется «e.emit ('myEvent', p1, p2)», мой код контролируетУзел основного потока (не цикл событий).И функция «emit» является синхронной, поэтому «emit» вызывает в этот самый момент каждого из слушателей, подключенных к «myEvent» (в приведенном выше примере N слушателей).Таким образом, фактически, вызов "e.emit ('myEvent', p1, p2)" эквивалентен выполнению следующих вызовов в традиционной императивной парадигме:

Listener1(p1,p2);
Listener2(p1,p2); 
... 
ListenerN(p1,p2);  

И если N большое, I 'Я блокирую цикл событий, потому что его текущий код контролирует основной поток, а не цикл событий.

Этот сценарий верен и возможен?По этой причине по умолчанию Node.js имеет максимум 10 слушателей?

Заранее спасибо!

1 Ответ

1 голос
/ 05 января 2012

Поскольку Javascript (без создания дочерних процессов вручную) является однопоточным, все, что вы выполняете в коде, означает, что он выполняется последовательно. Сам язык синхронный. В случае, если вы используете EventEmitter для добавления прослушивателей, он все равно выполняет все одно за другим по мере их добавления. Возможно подавить Node кучей ручных сообщений о событиях, но это все равно, что иметь цикл while(true), который будет иметь аналогичный результат. EventEmitter есть, просто чтобы иметь возможность использовать тот же шаблон, что и встроенные модули. Примерный эквивалент EventEmitter будет следующим:

var handlers = [];

function addHandler(fn) {
  handlers.push(fn);
}

function emit() {
  for (var i = 0; i < handlers.length; i++) {
    handlers[i]();
  }
}

// Add a bunch of handlers
addHandler(function(){console.log('foobar 1');});
....
addHandler(function(){console.log('foobar N');});

// Fire the event
emit();

Асинхронная часть представляет собой комбинацию ОС и Node, которая позволяет делегировать задачи, такие как чтение файлов, буферизацию и т. Д., Самой ОС, которая в основном выполняет это в другом потоке, оставляя Node свободным для запуска цикла обработки событий. Когда ОС запускает событие для Node о том, что чтение файла завершено, она затем выполняет необходимые изменения, которые вы написали в вашем JS. Во время выполнения обработчика завершенного чтения файла весь цикл событий по-прежнему останавливается, поскольку в любой момент существует один экземпляр выполнения JS.

Из документации :

По умолчанию EventEmitters выводит предупреждение, если больше 10 слушатели добавлены к этому. Это полезное значение по умолчанию, которое помогает обнаружение утечек памяти. Очевидно, что не все эмиттеры должны быть ограничены 10.

Надеюсь, это хоть что-то прояснило.

...