How Node.js emitter works? Understand passing arguments - node.js

I don't understand how the function(msg)... is called with myEmmiter.emit.
How does the .emit('someEvent', ...) know that the argument 'the event was emitted' should be passed to function(msg)...?
Is there a way to see the emit method source?
const events = require('events');
var myEmmiter = new events.EventEmitter();
myEmmiter.on('someEvent', function (msg) {
console.log(msg);
});
myEmmiter.emit('someEvent', 'the event was emitted');

The implementation for the events module can be found here: https://github.com/nodejs/node/blob/master/lib/events.js
In abstract, an EventEmitter instance maintains an object where the keys are the event names (someEvent) and the values are arrays of functions that should be called whenever that event is generated:
this.registeredEvents = {
someEvent : [ handler ]
};
To register for an event, you use emitter.on()/emitter.addListener():
on(eventName, handler) {
if (! Array.isArray(this.registeredEvents[eventName])) {
this.registeredEvents[eventName] = [];
}
this.registeredEvents[eventName].push(handler);
}
When you call emitter.emit(), each handler is called with the argument:
emit(eventName, message) {
(this.registeredEvents[eventName] || []).forEach(handler => handler(message));
}

Related

How I can get timers list in Node JS?

For example I have .js file, it's a single script. I have some functions In this script and this functions are making some timers (setTimeout). All of this timers wasn't associated with the variables.
Like a
function zzz(){
setTimeout(yyy, 100);
};
I need to know when all of this timers will be done, if Node JS has some event for it. Or I need list of all timers in this script, if it exists. To check length of this list in any random moment for example.
You could create an EventEmitter and emit an event at the end of your setTimeout callback. You can then work a solution to track when all of your expected events have fired around this. Extending the example in the docs:
'use strict';
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (data) => {
console.log(data); // yyy
});
function yyy() {
return;
}
setTimeout(() => {
yyy();
myEmitter.emit('event', 'yyy');
}, 100);

How to add two function as callback in node?

How can I callback two function in node?
For example:
request('http://...',[func1,func2])
Is there any module for that?
Is there some reason you can't put a wrapper around the two functions, then use the wrapper as a callback? For example:
function handleCallback(data)
{
func1(data);
func2(data);
}
request('http://...',handleCallback);
As noted in other answers it's trivial to wrap multiple functions in a single callback. However, the event emitter pattern is sometimes nicer for handling such cases. A example might be:
var http = require('http');
var req = http.request({ method: 'GET', host:... });
req.on('error', function (err) {
// Make sure you handle error events of event emitters. If you don't an error
// will throw an uncaught exception!
});
req.once('response', func1);
req.once('response', func2);
You can add as many listeners as you like. Of course, this assumes that what you want your callbacks to be registered on is an event emitter. Much of the time this is true.
You can create a little module for that:
jj.js file:
module.exports.series = function(tasks) {
return function(arg) {
console.log(tasks.length, 'le')
require('async').eachSeries(tasks, function(task, next) {
task.call(arg)
next();
})
}
}
example of use:
var ff = require('./ff.js')
function t(callback) {
callback('callback')
}
function a(b) {
console.log('a', b)
}
function b(b) {
console.log('b', b)
}
t(ff.series([a, b]))

Node.js delegating functions to an imported module

Currently I have a Node.js module with the following form :
var events = require('events');
var emitter = new events.EventEmitter();
function emitSomething() {
emitter.emit("event");
}
exports.emitSomething = emitSomething;
exports.on = emitter.on;
However any callback registered through on do not get called when I call emitSomething.
I can get around this by changing the last line to
exports.on = function(event, callback) { emitter.on(event, callback); };
Is there a reason I can't delegate the on function to a function defined in another module?
This is a common JS mistake. Note that the on method depends on this (which is emitter in your example). However, all you export is the function itself, so it's context (emitter) is lost when you call it later.
Here is a small example for this issue:
var someObj = {
doSth: function() { console.log(this) }
};
someObj.doSth(); // "Object { ..."
var doSth = someObj.doSth;
doSth(); // "Window { ..."
When I call doSth as method of someObj, this references someObj as expected. After I copied the function to doSth, this references it's new context, in the browser the global context Window. This is what happens in your case.
As you already mentioned, you have to bind the emitter context to the function. This can also be done like this:
exports.on = emitter.on.bind(emitter);

node.js EventEmitter causes scope problems

When using nodejs event system, I met with an annoying problem. As the code below shows, when a listener catch a event, the event emitter object owns 'this' in the callback function instead of the listener.
It's not a big problem if you put the callback in the listener's constructor, because besides pointer 'this', you can still use other variables defined in the constructor's scope, like the 'self' or 'that' way.
But, if the callback is put outside the constructor like the prototype methods, it appears to me that there is no ways to get the listener's 'this'.
Not very sure if there are any other solutions. And also, a little confused about why nodejs event emit use the emitter as the caller install of the listener?
util = require('util');
EventEmitter = require('events').EventEmitter;
var listener = function () {
var pub = new publisher();
var self = this;
pub.on('ok', function () {
console.log('by listener constructor this: ', this instanceof listener);
// output: by listener constructor this: false
console.log('by listener constructor self: ', self instanceof listener);
// output: by listener constructor this: true
})
pub.on('ok', this.outside);
}
listener.prototype.outside = function () {
console.log('by prototype listener this: ', this instanceof listener);
// output: by prototype listener this: false
// how to access to listener's this here?
}
var publisher = function () {
var self = this;
process.nextTick(function () {
self.emit('ok');
})
}
util.inherits(publisher, EventEmitter);
var l = new listener();
Try binding the listener explicitly to the callback:
pub.on('ok', this.outside.bind(this));

Node JS : Requesting for code snippet explanation

I am just curious to know what is the purpose of,
function MyStream() {
events.EventEmitter.call(this);
}
in the following block of code taken from Nodejs.org Docs section,
var util = require("util");
var events = require("events");
function MyStream() {
events.EventEmitter.call(this);
}
util.inherits(MyStream, events.EventEmitter);
MyStream.prototype.write = function(data) {
this.emit("data", data);
}
var stream = new MyStream();
console.log(stream instanceof events.EventEmitter); // true
console.log(MyStream.super_ === events.EventEmitter); // true
stream.on("data", function(data) {
console.log('Received data: "' + data + '"');
})
stream.write("It works!"); // Received data: "It works!"
Please explain.
This isn't the first time this question has been asked: https://groups.google.com/forum/#!topic/nodejs/ab_Xih1L5R8/discussion
Quote from Bradley Meck:
Using EventEmitter.call on an object will do the setup of instance methods / properties (not inherited) of an EventEmitter. It is similar in purpose to super(...) in Java or base(...) in C#, but it is not implicit in Javascript. Because of this, we must manually call it ourselves. As for the talk about util.inherits, this will make the MyStream function inherit from another prototyped function so that instanceof works (side note: javascript only allows single inheritance). Due to how the new operator works, if we have the this variable in a function set to an instanceof EventEmitter, and call EventEmitter.call it look for all intents and purposes as if EventEmitter's constructor is being called on our MyStream object.

Resources