Adding event listener on instance, not function - node.js

See example below. I am trying to trigger an event on a.
var events = require("events");
function foo() {
this.on("ping", function() {
console.log("bar!");
})
}
foo.prototype = new events.EventEmitter();
var a = new foo();
var b = new foo();
a.emit("ping");
This prints "bar!" two times, so I am assuming I am adding the event listener on "all" the functions, not the specific instance. Since I am running foo two times, I am adding two event listeners, nothing strange really, althought not so intuitive.
Is there a way to add the event listener only on a?
(Please edit this question if I am using the wrong terminology, used to class-based programming)
edit: So I suspect it is because I am using the same event emitter as prototype.. But in that case, how can I create one for each new foo()?

Typically you inherit (from EventEmitter) like this:
var inherits = require('util').inherits,
EventEmitter = require('events').EventEmitter;
function Foo() {
if (!(this instanceof Foo))
return new Foo();
EventEmitter.call(this);
this.on('ping', function() {
console.log('bar!');
});
}
inherits(Foo, EventEmitter);
// add Foo-specific prototype functions *after* `inherits()`
Foo.prototype.myfunc = function(a, b) {
return a + b;
});
var a = new Foo();
var b = new Foo();
a.emit('ping');
This is the setup that most modules on npm and objects in node core use to inherit from another object.

Related

Unsure why a jest test is failing

I have the following test code. The test is failing, but I'm not entirely sure why (I have a suspicion, but I'm unsure of how to fix it). Here are the high level classes:
// file myFile.js
const EventEmitter = require('events').EventEmitter;
const em = new EventEmitter();
class Foo {
constructor () {
this.support = 0;
em.on('onNewValue', this._handleNewValue.bind(this));
}
_handleNewValue (newValue) {
this.support = newValue;
console.log(this.support); // Prints whatever newValue is
}
}
class Bar {
setValue (newValue) {
em.emit('onNewValue', newValue);
}
}
Here's the test
const foo = new Foo();
expect(foo.support).toEqual(0); // Passes - initial value of support is 0
const bar = new Bar();
bar.setValue(10); // Emits an event that causes foo to set it's internal support value to 10.
console.log('Checking support'); // This prints after the console.log in foo._handleNewValue.
expect(foo.support).toEqual(10); // This fails - still reports initial value of 0
The high-level idea is that bar.setValue() emits an event that is listened to by the Foo class. The event listener updates the value of it's internal member support to be what the event payload is.
The test fails and reports the initial value of support. My hunch is that there is some timing issue going on (the expect gets called first, and then the event listener inside the Foo class).
However, if I console.log, the log in the event listener prints first, and then the log for 'Checking support', which does not seem to go along that theory.
Could someone help me figure out why this test is failing, and how to fix it? I don't want to explicitly call foo._handleNewValue in the test.
I tried your code using jest and it worked perfectly. Here's what I've tried
// file myFile.js
const EventEmitter = require('events').EventEmitter;
const em = new EventEmitter();
class Foo {
constructor() {
this.support = 0;
em.on('onNewValue', this._handleNewValue.bind(this));
}
_handleNewValue(newValue) {
this.support = newValue;
console.log(this.support); // Prints whatever newValue is
}
}
class Bar {
setValue(newValue) {
em.emit('onNewValue', newValue);
}
}
test('should catch bar emitted event', () => {
const foo = new Foo();
expect(foo.support).toBe(0)
const bar = new Bar()
bar.setValue(10)
expect(foo.support).toBe(10)
})

Calling another function of a class from within the same class, when this refers to something else [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
We have this code:
class Example {
constructor(num) {
this.a = num;
this.eventEmitter = null;
}
doSomething() {
// This doesn't work because 'this' will refer to the emitter.
this.a += 1;
}
registerEvents(eventEmitter){
this.eventEmitter = eventEmitter;
eventEmitter.on('event', this.doSomething);
}
}
and we want to bind it to an event emitter, like this:
function ExampleUser() {
const EventEmitter = require('events');
eventEmitter = new EventEmitter();
var reactor = new Example(1);
reactor.registerEvents(eventEmitter);
eventEmitter.emit('event');
}
The problem is, that when doSomething() is called, just like supposed, the this refers to the emitter, not to the Example object. Therefore, it cannot update this.a as we would like.
Help?
You need to bind your event listener to your Example instance:
registerEvents(eventEmitter){
this.eventEmitter = eventEmitter;
eventEmitter.on('event', this.doSomething.bind(this));
}

How to add event ability to object instance in Node?

It's ok to add event ability to a constructor:
function Stream() {
events.EventEmitter.call(this);
}
util.inherits(Stream, events.EventEmitter);
But how to add event ability to an object instance? The following code doesn't work:
var foo = {x: 1, y: 2};
util.inherits(foo, event.EventEmitter);
events.EventEmitter.call(foo);
After running the above code, foo.on still be undefined.
Is there a way to inherit or mix-in EventEmitter's content?
You can use the npm module node.extend.
It is a port of jQuery's $.extend and with it, you can do this:
var extend = require('node.extend'),
events = require('events');
extend(foo, events.EventEmitter.prototype);
or, if you don't want to use another module, you can use this:
function extend(target) {
var sources = Array.prototype.slice.call(arguments, 1);
return sources.forEach(function (source) {
Object.keys(source).forEach(function (key) {
target[key] = source[key];
});
}), target;
}
var events = require('events');
var foo = {x: 1, y: 2};
extend(foo, events.EventEmitter.prototype);

Object Based EventListener/EventEmitter in NodeJS?

I suddenly realized that event emitter in NodeJS is usually like a static method in Java.. Example:
// This illustrated that event listener is universal
function A(a){
var that = this;
this.a = a;
this.cnt = 0;
this.done = function(){
this.emit("done");
};
this.say = function(){
console.log(a + " = " + that.cnt);
};
this.inc = function(){
that.cnt++;
};
}
A.prototype = new events.EventEmitter;
var a = new A("a"),
b = new A("b"),
c = new A("c");
a.on("done",function(){a.inc()});
b.on("done",function(){b.inc()});
c.on("done",function(){c.inc()});
c.done();
c.done();
a.say();
b.say();
This code would give output:
a = 2
b = 2
While I'm actually expecting:
a = 0
b = 0
I believe this is because of the line:
A.prototype = new events.EventEmitter;
and I think the "prototype" kind of definition would be used like "static" in Java.
In order to have per-object based event listener, I changed the above code to be:
function B(a){
var that = this;
this.evt = new events.EventEmitter;
this.a = a;
this.cnt = 0;
this.done = function(){
this.evt.emit("done");
};
this.say = function(){
console.log(a + " = " + that.cnt);
};
this.inc = function(){
that.cnt++;
};
}
var a = new B("a"),
b = new B("b"),
c = new B("c");
a.evt.on("done",function(){a.inc()});
b.evt.on("done",function(){b.inc()});
c.evt.on("done",function(){c.inc()});
c.done();
c.done();
a.say();
b.say();
This would be per-object event listener, but I don't really think that is a good design/implementation because it breaks the chaining of EventEmitter. I.e., like code bellow:
// can chain another method of A after the on() method
a.on("event",functionCallback).anotherMethodOfA();
I'd like to ask, what's a proper implementation of the per-object event listener in NodeJS?
You can use addListener or on to attach listeners to your custom events. You won't need to chain calls on these methods. Of course you can inherit any object from EventEmitter and add emitting functionality to your object. You can inherit your object from an instance of EventEmitter. There's is function called inherit in the util library which does that for you.
var util = require('util');
var eventEmitter = require('events').EventEmitter;
// Now create your constructor/object.
function MyObj(a, b) {
this.a = a;
this.b = b;
.
.
.
}
util.inherits(MyObj,eventEmitter);
// Implement your methods and add the functionality you need.
MyObj.prototype.aMethod = function(arg) {
.
.
.
// Define how to emit events
if (arg == 'A')
this.emit('eventA', this.a);
else if (arg == 'B')
this.emit('eventB');
// Return this for chaining method calls
return this;
}
MyObj.prototype.anotherMethod = function() {
// Add more functionality...
.
.
.
return this;
}
// Now instantiate the constructor and add listenters
var instanceOfMyObj = new MyObj('a parameter', 'another parameter');
instanceOfMyObj.on('eventA', function(a){
// Handle the event
});
// Now chain calls..
instanceOfMyObj.aMethod('A').anotherMethod(); // This will trigger eventA...

util.inherits - how to call method of super on instance?

I'm playing with util.inherits method from node.js and can't seem to get the desired behavior.
var util = require("util");
function A() {
this.name = 'old';
}
A.prototype.log = function(){
console.log('my old name is: '+ this.name);
};
function B(){
A.call(this);
this.name = 'new';
}
util.inherits(B, A);
B.prototype.log = function(){
B.super_.prototype.log();
console.log('my new name is: ' + this.name);
}
var b = new B();
b.log();
The result is:
my old name is: undefined
my new name is: new
However what I would like is:
my old name is: new
my new name is: new
What am I missing?
Here's how to achieve what you are looking for:
B.prototype.log = function () {
B.super_.prototype.log.apply(this);
console.log('my new name is: ' + this.name);
};
This ensures the this context is the instance of B instead of being B.super_.prototype I suppose.
I prefer to call method of super through prototype chain instead of constructor chain like following.
var prototype = C.prototype;
prototype.log = function() {
Object.getPrototypeOf(prototype).log.call(this)
// or old style
prototype.__proto__.log.call(this)
}
They are all accessing prototype object of super class, but using prototype chain might be better than constructor.super_.prototype of constructor chain.
because usually I hide protected, private methods in separated files and under a prototype folder. Only public methods are with the constructor function in the same scope. In addition, to make them easy to move around different classes. All of them are named as prototype.method = function() {...}, so most of them can only access the prototype object.
Or it would be appreciated to know any benefit to go through constructor chain? This is why I found this post.

Resources