EventEmmitter: access the event from within the callback - node.js

Can I have access to the name of an event from within the callback which is executed when the event is triggered?
Consider the following example, where I have the same callback (handleEvent)for two differenct events. Now I want to add a conditional statement in the callback based on the event that triggered its execution. Is this possible?
obj.on('start', handleEvent);
obj.on('stop', handleEvent);
function handleEvent() {
// how can I check here if the event that triggers the execution of handleEvent is 'start' or 'stop'
}
What I do at the moment is to pass the event two times with 'emit' - which seems to be working fine, but i don't like to write it twice:
obj.emit('start', 'start', handleEvent);

Try EventEmitter2:
var EventEmitter = require('eventemitter2').EventEmitter2
var emitter = new EventEmitter
emitter.on('test', onEvent)
emitter.emit('test')
function onEvent() {
console.log(this.event)
}

You can do:
obj.on('start', handleEvent.bind({ event: 'start' }));
obj.on('stop', handleEvent.bind({ event: 'stop' }));
function handleEvent() {
if(this.event == 'start') { ///
}

Related

why should one register listener first and call emit method next in node.js?? can't we reverse the order and still be able to work?

Why is order of listener should be on top of emitter?
const EventEmitter=require('events');
const emitter=new EventEmitter();
//Register a Listener
emitter.on('messageLogged',function(){
console.log('Listener Called');
})
//Raise an event
emitter.emit('messageLogged');
Because you need to subscribe a listener to the event before you emit an event.
The idea is that when you call emit it will call functions you attached to the event. If there is no function it will call nothing. You can not call a function that is attached in the future for an event that you emit at the moment.

Events & Event Emitter in Node.js

So I've attached two events if someone screams, they are called synchronously, why so?
const events = require('events');
const eventEmitter = new events.EventEmitter();
eventEmitter.on('scream', function() {
console.log("Screaming");
});
eventEmitter.on('scream', function(name) {
console.log(name+" is screaming");
});
eventEmitter.emit('scream', 'Bob');
O/P:
Screaming
Bob is screaming
Because in nodejs, The event loop is single threaded and pick one event at a time and treat those events independently.
In your case, there are two event handler with the same name, so when event loop gets the eventEmitter.emit('scream', 'Bob') it sends the particular event handler.
When first event handler done with it, Now it goes to the second handler because with the same name.
It follow the FIFO but if you use emitter.prependListener(eventName, listener) then it will be executed first the FIFO.
You should know, if you want to call only one time then you should use eventEmitter.once('scream') It will be called only one time.
eventEmitter.once('scream', function() {
console.log("Screaming");
});
eventEmitter.emit('scream', 'Bob');
eventEmitter.emit('scream', 'Bob');
eventEmitter.emit('scream', 'Bob');
Output: Screaming // Only one time.
Because the Event loop fetches events from Event Queue and sends them to call stack one by one.
And Event Queue is FIFO (First-In-First-Out)

Keep event listeners alive after script completion in Node js

I have two .js file. One emits the event and another listens for it. The code looks as below.
Emitter
var EventEmitter = require('events').EventEmitter;
utils.inherits(ConfigFileManager, EventEmitter);
var manager = new ConfigFileManager();
var watcher = chokidar.watch(CONFIG_DIR, {persistent: true});
watcher.on('add', function (path) {
manager.emit('monitor', 'print this data');
});
watcher.on('change', function (path) {
console.log('change event fired');
manager.emit('monitor', 'print this data');
});
module.exports = manager;
The chokidar.watch keeps the event queue and restricts node from exiting. Now, listener is in different file, as given below.
Listener
var manager = require('./emitter');
manager.on('monitor', function(data) {
console.log(data);
});
and I run "node listener.js". The first time "add" event calls the listener, and all is fine. However when I change a file, the event is emitted, but the listener never gets it. If I add a setTimeout at the end of the listener.js, the listener is getting events until the timeout expires. So, once the listener script completes, the events are not received. How can I make the listener to listen forever?
Also, if I keep the listener code also in emitter.js, then it works, because chokidar.watch keeps the script from terminating. But, I want to keep them separate for better organization.

Is there a way to trigger plotselected event without triggering plotclick event?

I need click events in the chart.
But I also need to allow user to select a range to zoom in.
Click events are registered properly. However on doing a selection, it triggers both plotselected and plotclick events.
How do I prevent the plotclick event from being triggered while plotselected is triggered?
Selection plugin: https://github.com/flot/flot/blob/master/jquery.flot.selection.js
Currently no, there's no way to avoid getting both events.
One solution might be to remove the 'clickable' option and instead listen to the 'plotunselected' event, which is triggered by a click without drag.
The problem is plotselected triggering plotclick event.
The following conditional check solved my problem.
$("#graph").bind("plotclick", function (event, pos, item) {
if (item == undefined) return false;
// the rest of the click event here
});
resting's answer didn't quite work for me as my use case needed to handle the plotclick event even if there was no item clicked.
I was able to determine if an event was a plotselection vs plotclick event in the plotclick event handler by setting a variable in the plotselection event handler and then checking it in the plotclick handler:
var plotSelectionEvent = false;
$("#placeholder").bind("plotselected", function (event, ranges) {
plotSelectionEvent = true;
// rest of the plot selection event code
});
$("#placeholder").bind("plotclick", function (event, pos, item) {
// check if this event was originally a plot selection event
// reset the variable and return if it was
if (plotSelectionEvent) {
plotSelectionEvent = false;
return;
}
// rest of the plot selection event code
});

Node.js event scope?

I would like to use an event in node.js to execute some code; my question is, what is the scope of the invoked event code? Specifically, does it share the scope of the event invoker, or is it "isolated"? I know that I can pass parameters to the code invoked on the event to achieve a similar effect, but ideally I'd like to have the invoking scope available.
The event is tied to the scope of the invoker. i.e. an EventEmitter exported from a module, can only be used to listen for events emitted from that same EventEmitter.
Nodejs EventEmitter - Define scope for listener function
When you emit an event, you put it into a queue to be processed later by the node event system. Any variables from the scope where the event is emitted must be passed to emit as arguments. When node takes that event and triggers all bound callbacks, that happens under both a distinct "clean" scope and a distinct "clean" stack. (Side note, this is why stack traces in node can be a nuisance for debugging).
var events = require('events');
var myEmitter = new events.EventEmitter();
function closure1(word, number) {
function closure2(animal, vegetable) {
myEmitter.emit('hey', word, number, animal, vegetable, 43);
}
closure2("horse", "carrot");
}
myEmitter.on('hey', function (word, number, animal, vegetable, anotherNumber) {
console.log('hey event fired with', word, number, animal, vegetable, anotherNumber);
});
closure1("table", 42);
When you run that, it will print "hey event fired with table 42 horse carrot 43".
see the node.js docs on emitter.emit(event, [arg1], [arg2], [...]

Resources