I have a question about events.EventEmitter
in Node.js, why use it? What is the difference with example 1 and example 2? I find them identical, are they? When is it practical to use it?
let events = require("events");
let util = require("util");
let eventEmitter = new events.EventEmitter();
Example 1 with the EventEmitter
:
let Student = function(name) {
this.name = name;
}
util.inherits(Student, events.EventEmitter);
let student_max = new Student('max');
student_max.on('scored', function(points) {
if (points > 90) {
points = points + ' wow you scored more than 90'
}
console.log(`${this.name} ${points} points`);
})
student_max.emit('scored',95);
Example 2 without EventEmitter
let Student2 = function(name) {
this.name = name;
this.score = function(str,points) {
if (str!=='scored') {
return;
}
if (points > 90) {
points = points + ' wow you scored more than 90'
}
console.log(`${this.name} ${points} points`);
}
}
let student_lenny = new Student2('Lenny');
student_lenny.score('scored',95);
The first example subclasses an event emitter and then uses that event emitter to implement some functionality. That means that anyone else can take one of your student_max
objects and register an event listener for the scored
message or they could even emit a scored
message themselves. You could then very easily use the eventEmitter
functionality to extend to other events that occurred in your object and then any third party could observe or trigger those events too. eventEmitter
is a standardized way of exposing event based functionality. You can accomplish things with an eventEmitter
by designing your own notification schemes, but it is often better to build on a standard scheme that lots of developers already know and that has a fair amount of functionality already built in.
Your second example as currently coded accomplishes the same thing, but is not as extensible. For example, if you wanted to know anything a score
happens, you would have to subclass the object and override the score method rather than just adding a listener to an event using the well-established eventEmitter
interface. If you didn't create the object yourself (which makes it hard to subclass), then you'd have to monkey-patch the score
method in order to observe it.
what is the difference of the example1 to example2
It's an architectural difference that affects both how outside agents interact with these objects and how extensible they are in the future.
The use of the eventEmitter
in example1 is very extensible and makes it easy to add future events to the object using the eventEmitter
features or for outside agents to monitor or trigger events using a standardized interface. So, the difference is not in exactly what the code you show achieves, but in how it is architected and thus how extensible it would be in the future or how outside code could interact with your object
When is it practical to use it?
You would think about using an eventEmitter
object pretty much anytime you want outside parties to be able to observe events or trigger events on your object in a lightweight and easy way. It's a pre-built system for that and is often better than inventing your own callback notification scheme. And sometimes, it is useful even for your own implementation when you aren't trying to enable outside interactions.