Node.js EventEmitter and several levels of inheritance

I am trying to find a better approach to multiple levels of inheritance when using the Node.js EventEmitter class.

Customization: I am developing an MVC environment for Node.js using controllers that can have base controllers, but controllers can generate events that also emit the same event on its base controller. So far, I:

 var events = require('events'); var util = require('util'); var Controller = function() { }; util.inherits(Controller, events.EventEmitter); var baseController = new Controller(); baseController.on('request', function() { console.log('Calling request event on baseController'); }); var homeController = new Controller(); homeController.prototype = baseController; homeController.on('request', function() { console.log('Calling request event on homeController'); }); homeController.emit('request'); 

... but only "Calling a request to homeController" is displayed, I want both "request" events to fire. How can I do it? Maybe I need to completely change my approach?


Update: thanks for helping everyone. As Naor Bitton suggested, there was no inheritance between baseController and homeController, since the 'prototype' property only matters to constructor functions. I always get my constructor functions and object instances to mix.

In the end, I decided:

 var events = require('events'); var util = require('util'); var Controller = function() { }; util.inherits(Controller, events.EventEmitter); Controller.createBaseController = function() { var BaseController = function() { }; util.inherits(BaseController, Controller); return new BaseController(); }; Controller.inheritController = function(baseController) { var NewController = function() { }; NewController.prototype = baseController; return new NewController(); }; var baseController = Controller.createBaseController(); baseController.on('request', function() { console.log('Calling request event on baseController'); }); var homeController = Controller.inheritController(baseController); homeController.on('request', function() { console.log('Calling request event on homeController'); }); homeController.emit('request'); 
+4
source share
2 answers

In your example, there is no inheritance relationship between homeController and baseController . In addition, this line:

 homeController.prototype = baseController; 

This is redundant because the prototype property is relevant only to constructor functions.

If you want to configure baseController so that the one who extends / inherits from it has a request listener assigned to it, you must first define it as follows:

 var BaseController = function(){ this.on('request', function(){ console.log('...'); }); }; BaseController.prototype = new events.EventEmitter(); BaseController.prototype.constructor = BaseController; 

It will be even better if you can assign a handler in the initiliazation method (working in the constructor function is usually bad):

 var BaseController = function(){}; BaseController.prototype = new events.EventEmitter(); BaseController.prototype.init = function(){ this.on('request', function(){ console.log('...'); }); }; 

And then all you need for an extension in the HomeController is to do this:

 var HomeController = function(){}; HomeController.prototype = new BaseController(); var homeController = new HomeController(); homeController.init(); // If you went with the initialization approach I offered... 

Please note that if you do not, creating long inheritance chains in JS is not very pleasant or supported. If you can, I recommend that you avoid this and try to find a more convenient solution.

+3
source

In your example, both homeController and baseController have the same prototype (which you can test with getPrototypeOf .prototype is an attribute of functions .

If you want to directly set the prototype of an object to another object without using a function and setting your prototype, you can use Object.create

Here is what I would do in your case, by the way (using less prototypal inheritance and more structural subtyping).

 function Controller(){ var obj = new events.EventEmitter(); // Add stuff to controller here obj.on("request",function(){ console.log('Calling request event on baseController'); }); return obj; } function HomeController(){ var obj = new Controller(); obj.on('request', function() { console.log('Calling request event on homeController'); }); return obj; } var homeController = new HomeController(); // can create a Controller and add // an event just fine. If you want explicit // structural subtyping we need HomeController homeController.emit("request"); 
+2
source

Source: https://habr.com/ru/post/1492564/


All Articles