Должны ли генераторы событий node.js быть привязаны к пользовательскому объекту, чтобы использовать их эффективно?

Почему в node.js некоторые примеры эмиттеров событий выглядят просто так:

EventEmitter = require("events").EventEmitter;
ee1 = new EventEmitter;

а затем ee1 используется для отправки и прослушивания событий.

Другие примеры выглядят так:

EventEmitter = require("events").EventEmitter;
util = require("util");

MyFunc = function ()
   EventEmitter.call(this);
}
util.inherit(MyFunc, EventEmitter);

ee2 = new MyFunc();

а затем ee2 используется для отправки и прослушивания событий.

Можете ли вы использовать ee1 для обработки всех событий (отправляя их куда угодно, например, в свой пользовательский объект). В чем причина привязки прототипа эмиттера событий к вашим собственным объектам/функциям?


person ciso    schedule 02.04.2014    source источник


Ответы (2)


В этом нет ничего неправильного, но если вы планируете пойти по пути ee1, я предлагаю вам изучить Шаблон агрегатора событий. При небольшом тщательном планировании вы сможете избежать некоторых ошибок с одной шиной событий.

Лично я всегда предпочитал ee2 способ ведения дел. Я думаю, что это делает вещи немного более организованными (инкапсулированными).

person maček    schedule 03.04.2014
comment
Ваш четкий ответ и поддерживающая статья очень помогли. Я подозревал, что это так, но не был уверен. Я могу закончить с комбинацией обоих шаблонов. Некоторые общие события и некоторые инкапсулированные, где это имеет смысл. Теперь я также знаю, как это называется (паттерн агрегатора событий). Спасибо. - person ciso; 03.04.2014

Идея состоит в том, что ваш объект является EventEmitter. Используя ваши имена, это позволяет вам сделать что-то вроде:

ee2.on('some-event', ...);

при этом также обычно используя ваш объект:

ee2.myOwnFunction();
person Henry Merriam    schedule 02.04.2014
comment
Да, но нужно ли вам делать это таким образом, чтобы использовать их эффективно? Можете ли вы просто сделать это проще, используя ee1 в моем примере в качестве объекта-эмиттера событий вместо замены прототипа на ваши различные пользовательские объекты/классы и заставляя их испускать через свои собственные функции-прототипы? - person ciso; 03.04.2014
comment
Я бы сказал, что да. Использование ee1 поднимает вопрос: как другие части вашего кода получают доступ к этому экземпляру? Вам нужно будет передать как ваш объект, так и его эмиттер событий, или передать объект с эмиттером событий в качестве свойства. Ни то, ни другое не является особенно жидким. Самое главное, оба нарушают наиболее распространенный шаблон для EventEmitter, который заключается в расширении прототипа. Теперь вы можете добавить свои собственные свойства и функции в ee1 вместо написания собственного конструктора, но это работает только для очень простых объектов (поскольку у вас не будет конструктора). - person Henry Merriam; 03.04.2014
comment
ee1 будет доступен, поскольку он глобальный или находится в модуле, или его можно сделать доступным через замыкание. - person ciso; 03.04.2014
comment
Глобальные значения — плохая идея по причинам, которые вы найдете с помощью быстрого поиска в Google. Если ваш эмиттер доступен только в некоторой локальной области, тогда это работает, но, вероятно, это неправильный инструмент для работы. Это также означает, что позже вы не сможете прослушивать события за пределами этой области. Этот эмиттер лучше встроить в другой объект. Другими словами: если вы действительно просто вызываете функцию в локальной области видимости, просто вызовите функцию вместо добавления уровня абстракции (который в любом случае не может быть эффективно использован, поскольку он имеет область действия). - person Henry Merriam; 03.04.2014
comment
Ну, всем программам javascript нужен хотя бы один глобальный объект (ваш код). ee1 будет просто перенесен на этот глобальный объект и доступен для всех функций и объектов в вашем коде. Я все еще ищу окончательный ответ на свой первоначальный вопрос. - person ciso; 03.04.2014
comment
Я объяснил, как шаблон расширения используется для достижения инкапсуляции. Если вы действительно хотите использовать эмиттер с глобальной областью действия, вы можете, но это почти всегда плохой дизайн. Сам эмиттер будет работать нормально, если вы создадите его из EventEmitter. Однако на практике это не делается по причинам, которые я перечислил. (Вы можете построить машину без двигателя и ездить на ней... но не должны.) - person Henry Merriam; 03.04.2014
comment
Итак, я думаю, вы говорите, что я могу использовать первый шаблон и эффективно использовать эмиттеры событий для всех объектов и функций (если вы действительно этого хотите), например, в моей библиотеке (определенной глобально) и не нужно менять прототип моих пользовательских объектов/классов? Но вы считаете, что это плохой дизайн по причинам, которые я еще не совсем понимаю. Я не вижу аналогии с автомобилем/двигателем и, конечно же, не хочу использовать функции вместо этого, поскольку весь смысл генераторов событий заключается в том, чтобы включить неблокирующую асинхронную активность (особенно в отношении ввода-вывода). - person ciso; 03.04.2014
comment
EventEmitter не для облегчения асинхронной активности; вы можете просто использовать для этого Process.nextTick() или некоторые библиотеки более высокого уровня (например, асинхронные), которые его используют. События по-прежнему могут выполняться синхронно! - person Henry Merriam; 03.04.2014