tutorial react property nodejs node new event emitter driven addlistener node.js eventemitter

react - Node.js-hereda de EventEmitter



node js events tutorial (6)

Herencia de Clase de Estilo ES 6

Estos vienen directamente de los documentos, pero pensé que sería bueno agregarlos a esta pregunta popular para cualquier persona que busque.

const EventEmitter = require(''events''); class MyEmitter extends EventEmitter { constructor() { super(); //must call super for "this" to be defined. } } const myEmitter = new MyEmitter(); myEmitter.on(''event'', () => { console.log(''an event occurred!''); }); myEmitter.emit(''event'');

Me gustaría dar las git thank quien haya agregado eso. Emisor de eventos .

Nota: La documentación no llama a super() en el constructor que hará que this no esté definido. Mira este issue .

Veo este patrón en bastantes bibliotecas de Node.js:

Master.prototype.__proto__ = EventEmitter.prototype;

(fuente here )

¿Puede alguien explicarme por favor con un ejemplo, por qué este es un patrón tan común y cuándo es útil?


Así es como se hace la herencia prototípica (prototipal?) En JavaScript. De MDN :

Se refiere al prototipo del objeto, que puede ser un objeto o nulo (lo que generalmente significa que el objeto es Object.prototype, que no tiene prototipo). A veces se usa para implementar la búsqueda de propiedades basada en la herencia del prototipo.

Esto también funciona:

var Emitter = function(obj) { this.obj = obj; } // DON''T Emitter.prototype = new require(''events'').EventEmitter(); Emitter.prototype = Object.create(require(''events'').EventEmitter.prototype);

Comprender JavaScript OOP es uno de los mejores artículos que leí últimamente sobre OOP en ECMAScript 5.


Como dice el comentario anterior de ese código, hará que Master herede de EventEmitter.prototype , por lo que puede usar instancias de esa ''clase'' para emitir y escuchar eventos.

Por ejemplo, ahora puede hacer:

masterInstance = new Master(); masterInstance.on(''an_event'', function () { console.log(''an event has happened''); }); // trigger the event masterInstance.emit(''an_event'');

Actualización : como señalaron muchos usuarios, la forma "estándar" de hacer eso en Node sería usar ''util.inherits'':

var EventEmitter = require(''events'').EventEmitter; util.inherits(Master, EventEmitter);


Para agregar a la respuesta de wprl. Se perdió la parte del "prototipo":

function EventedObject(){ // Super constructor EventEmitter.call(this); return this; } EventObject.prototype = new EventEmitter(); //<-- you''re missing this part


Para heredar de otro objeto JavaScript, EventEmitter de Node.js en particular, pero realmente cualquier objeto en general, debe hacer dos cosas:

  • proporciona un constructor para tu objeto, que inicializa completamente el objeto; en el caso de que esté heredando de algún otro objeto, probablemente quiera delegar parte de este trabajo de inicialización en el super constructor.
  • proporcionar un prototipo de objeto que se usará como [[proto]] para objetos creados a partir de su constructor; en el caso de que esté heredando de algún otro objeto, probablemente quiera usar una instancia del otro objeto como su prototipo.

Esto es más complicado en Javascript de lo que podría parecer en otros idiomas porque

  • Javascript separa el comportamiento del objeto en "constructor" y "prototipo". Estos conceptos están destinados a usarse juntos, pero se pueden usar por separado.
  • Javascript es un lenguaje muy maleable y las personas lo usan de manera diferente y no existe una única definición verdadera de lo que significa "herencia".
  • En muchos casos, puede salirse con la suya haciendo un subconjunto de lo que es correcto, y encontrará miles de ejemplos a seguir (incluidas algunas otras respuestas a esta pregunta SO) que parecen funcionar bien para su caso.

Para el caso específico del EventEmitter de Node.js, esto es lo que funciona:

var EventEmitter = require(''events'').EventEmitter; var util = require(''util''); // Define the constructor for your derived "class" function Master(arg1, arg2) { // call the super constructor to initialize `this` EventEmitter.call(this); // your own initialization of `this` follows here }; // Declare that your class should use EventEmitter as its prototype. // This is roughly equivalent to: Master.prototype = Object.create(EventEmitter.prototype) util.inherits(Master, EventEmitter);

Posibles debilidades:

  • Si usa el prototipo para su subclase (Master.prototype), con o sin el uso de util.inherits , pero no llama al super constructor ( EventEmitter ) para las instancias de su clase, no se inicializarán correctamente.
  • Si llama al superconstructor pero no configura el prototipo, los métodos EventEmitter no funcionarán en su objeto
  • Puede tratar de usar una instancia inicializada de la superclase ( new EventEmitter ) como Master.prototype lugar de tener el constructor de la subclase Master call al superconstructor EventEmitter ; dependiendo del comportamiento del constructor de la superclase que pueda parecer que funciona bien por un tiempo, pero no es lo mismo (y no funcionará para EventEmitter).
  • Puede tratar de usar el prototipo directamente ( Master.prototype = EventEmitter.prototype ) en lugar de agregar una capa adicional de objetos a través de Object.create; esto podría parecer que funciona bien hasta que alguien envíe un parche a tu objeto Master e inadvertidamente también haya EventEmitter parche a EventEmitter y a todos sus otros descendientes. Cada "clase" debe tener su propio prototipo.

De nuevo: para heredar de EventEmitter (o realmente cualquier "clase" de objeto existente), quiere definir un constructor que encadena al super constructor y proporciona un prototipo que se deriva del super prototipo.


Pensé que este enfoque de http://www.bennadel.com/blog/2187-Extending-EventEmitter-To-Create-An-Evented-Cache-In-Node-js.htm era bastante claro:

function EventedObject(){ // Super constructor EventEmitter.call( this ); return( this ); }

Douglas Crockford también tiene algunos patrones de herencia interesantes: this

Encuentro que la herencia se necesita con menos frecuencia en JavaScript y en Node.js. Pero al escribir una aplicación donde la herencia podría afectar la escalabilidad, consideraría el rendimiento comparado con la capacidad de mantenimiento. De lo contrario, solo basaría mi decisión en qué patrones conducen a mejores diseños generales, son más fáciles de mantener y menos propensos a errores.

Pruebe patrones diferentes en jsPerf, usando Google Chrome (V8) para obtener una comparación aproximada. V8 es el motor de JavaScript utilizado tanto por Node.js como por Chrome.

Aquí hay algunos jsPerfs para que comiences:

http://jsperf.com/prototypes-vs-functions/4

http://jsperf.com/inheritance-proto-vs-object-create

http://jsperf.com/inheritance-perf