What is the difference between using the EventEmitter and just using functions? - node.js

As you can tell from this question, I'm very new to Node.js. If a question like this is not suited for this forum I do apologize and request that you direct me to a better place please.
I'm watching some training courses on Lynda and we are covering the EventEmitter. In the code below we have to add an event to the Person object. My question is, why add this event this way and not just add a function called speak to the Person object from the start? Thank you very much!
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var Person = function(name) {
this.name = name;
};
util.inherits(Person, EventEmitter);
var ben = new Person("Ben Franklin");
ben.on('speak', function(said) {
console.log(`${this.name}: ${said}`);
});
ben.emit('speak', "You may delay, but time will not.");

EventEmitter is helpful when you can't control (much) the generation of events. They can be caused by some asynchronous operation which you don't control. For example, a database disconnecting.
Here in the example, event is Ben speaking something. You don't control Ben.
You can respond to his event by defining a listener - a function which executes whenever the said event occurs.

Related

Chaining .emit( ) with EventListener in Node.js

When using the EventEmitter class in Node.js what is the best practice way to chain together different events?
Let's say I have multiple events, and I want to emit/trigger event 'B' but only inside the listener of some other initial event, 'A'. I was able to do something like that below, I'm just wondering if it is correct / memory-efficient to reference the eventEmitter instance in its own event listeners?
import {EventEmitter} from 'events';
const eventEmitter = new EventEmitter();
const eventTypes = ['txRequestReceived', 'txRequestComplete'];
eventEmitter.on('txRequestReceived', (params)=>{
let {chainID, address} = params;
console.log(`txRequestReceived event: ${chainID} -- ${address}`);
eventEmitter.emit('txRequestComplete', {"chainID": chainID, "address": address});
});
eventEmitter.on('txRequestComplete', (params)=>{
let {chainID, address} = params;
console.log(`txRequestComplete event: ${chainID} -- ${address}`);
});
This does work, and I'm able to pass around an event payload with the listener parameters. I'm wondering if there are memory / scope issues with it? If I were to write a class and extend the EventEmitter class, would I just use the 'this' keyword to access .emit() and .on() behaviour?
I was able to find this "answer" (which I will accept). The pattern I used works, but there are caveats surrounding the fact that EventEmitter is synchronous and how closures with the handlers may handle memory.
https://www.codementor.io/#simenli/demystifying-asynchronous-programming-part-2-node-js-eventemitter-7r51ivby4

Node.js, EventEmitter of why using it

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.

Correct usage of events in NodeJs - Concerning "this" context

I am designing a communication server in Node that handles incoming messages (sent by client1) and transfers them to someone else (client2), who answers the message and sends the answer back, via the server, to client1.
The communication happens via WebSockets, which implies an open connection from each client to the server.
Thus I implemented a ConnectionManager to which I can register any new connections when a new client comes online. Every connection gets assigned a messageQueue in which all incoming messages are cached before processing.
At the end of processing, I have a ServerTaskManager, who generates Output-Tasks for the server, telling him a message to send and a receiver to receive it.
This ServerTaskManager emits a Node-Event (inherits from EventEmitter) upon registering a new serverTask to which the server listens.
Now I would like my ConnectionManager to also listen to the event of the serverTaskManager, in order to make him push the next message in the messageQueue into processing.
Now the problem is, that I can catch the ServerTaskManager event within the ConnectionManager just fine, but, of course, the "this" within the listener is the ServerTaskManager, not the ConnectionManager. Thus calling any "this.someFunction()" functions that belong to the ConnectionManager won't work.
Here is some code:
/**
* ServerTaskManager - Constructor
* Implements Singleton pattern.
*/
function ServerTaskManager()
{
var __instance;
ServerTaskManager = function ServerTaskManager()
{
return __instance;
}
ServerTaskManager.prototype = this;
__instance = new ServerTaskManager();
__instance.constructor = ServerTaskManager;
return __instance;
}
util.inherits(ServerTaskManager, EventEmitter);
/**
* ConnectionManager - Constructor
* Also implements Singleton pattern.
*/
function ConnectionManager()
{
var __instance;
ConnectionManager = function ConnectionManager()
{
return __instance;
}
ConnectionManager.prototype = this;
__instance = new ConnectionManager();
__instance.constructor = ConnectionManager;
__instance.currentConnections = [];
// Listen for new serverInstructions on the serverTaskManager
serverTaskManager.on('newInstruction', function(messageObject, currentReceiver)
{
this.processNextMessage(currentReceiver);
});
return __instance;
}
util.inherits(ConnectionManager, EventEmitter);
Now when I run this and the "newInstructions" event is triggered by the serverTaskManager, node throws:
TypeError: Object #<ServerTaskManager> has no method 'processNextMessage'
Which is of course true. The function I want to call belongs to the ConnectionManager:
/**
* Starts processing the next message
*
* #param connectionId (int) - The ID of the connection, of which to process the next message.
*/
ConnectionManager.prototype.processNextMessage = function (connectionId)
{
// Some Code...
}
So obviously, when listening to the ServerTaskManager event, "this" within the listener is the ServerTaskManager. Now how do I call my ConnectionManager's function from within the listener?
I hope I am not completely misled by how events and listeners and/or prototypical extensions work (in Node). This project is by far the most advanced that I have worked on in JavaScript. Normally I am only coding PHP with a little bit of client side JS.
Thx in advance for any hints!
Worp
Like this.
serverTaskManager.on('newInstruction', function(messageObject, currentReceiver)
{
ConnectionManager.processNextMessage(currentReceiver);
});
Or like this.
serverTaskManager.on('newInstruction', function(messageObject, currentReceiver)
{
ConnectionManager().processNextMessage(currentReceiver);
});
PS: your question is unnecessarily long. When posting code, don't necessarily post your example. It is much easier to boil your code down to the simplest form that exhibits the behavior you are seeing. You'll get more quality responses this way.

Best way using events in node.js

Which is the best approach for listening/launching events in node.js?
I've been testing event launching and listening in node.js by extending the model with EventEmitter and I'm wondering if it has sense this approach since the events are only listened when there is a instance of the model.
How can be achieved that events will be listened while the node app is alive??
Example for extending the model using eventEmitter.
// myModel.js
var util = require('util');
var events2 = require('events').EventEmitter;
var MyModel = function() {
events2.call(this);
// Create a event listener
this.on('myEvent', function(value) {
console.log('hi!');
});
};
MyModel.prototype.dummyFunction = function(params) {
// just a dummy function.
}
util.inherits(MyModel, events2);
module.exports = MyModel;
EDIT: A more clear question about this would be: how to keep a permanent process that listens the events during the app execution and it has a global scope (something like a running event manager that listens events produced in the app).
Would be a solution to require the file myModel.js in app.js? How this kind of things are solved in node.js?
I'm not entirely sure what you mean about events only being active when there is an instance of a model since without something to listen and react to them, events cannot occur.
Having said that, it is certainly reasonable to:
util.inherits(global,EventEmitter)
global.on('myEvent',function(){
/* do something useful */
});
which would allow you to:
global.emit('myEvent')
or even:
var ee=new EventEmitter();
ee.on('myEvent',...)
As for how to properly use EventEmitter: it's defined as
function EventEmitter() {}
which does not provide for initialization, so it should be sufficient to:
var Thing=function(){};
util.inherits(Thing,EventEmitter);
which will extend instances of Thing with:
setMaxListeners(num)
emit(type,...)
addListener(type,listener) -- aliased as on()
once(type,listener)
removeListener(type,listener)
removeAllListeners()
listeners(type)
The only possible "gotcha" is that EventEmitter adds its own _events object property to any extended object (this) which suggests you should not name any of your own object properties with the same name without unexpected behavior.

NODE.JS accessing shared variable in socket.IO event handler

I am doing an experimental online poker game using NODE.JS and socket.IO. The game requires 3 players to join to start. I use socket.IO to listen to the connections from joining players. Whenever there are 3 players coming, they will form one group. Currently I use some shared variables to do this. But if there are lots of players coming in at the same time, I am fear it will cause synchronization problem. As you can see from the code snippet, the players, groups, groupNumber, comingPlayer, clients are all shared between multiple 'connection' event handlers. So when one event handler is executed and another event handler got scheduled by the V8 engine, it may corrupt the states of these shared variables.
I have done some research using Google but didn't find satisfactory answers. So I posted here to see if any expert can help me. Thanks in advance!
var clients = {}; // {"player1": 1} {"player2": 1} {"player3": 1}
var groups = {}; // {"1": ["player1", "player2", "player3"]
var groupNumber = 1; // the current group number
var comingPlayers = 0; // a temporary variable for the coming players
var players = []; // a temporary array containing the players which have not formed 1 group
socket.on('connection', function(client) {
sockets[client.id] = client;
players.push(client.id);
clients[client.id] = groupNumber;
comingPlayers++;
if (comingPlayers === 3) { // now there are 3 players which can compose 1 group
groups[groupNumber] = arrayClone(players);
gamePlay(groupNumber);
players = [];
groupNumber++;
comingPlayers = 0;
}
}
The code you've shown is atomic (it will completely finish before another event handler can run), so you shouldn't have any synchronization issues. Remember that in node, all user-written code runs in a single thread. If somebody else is trying to connect, it won't interrupt what you're doing.

Resources