EventEmitter has no emit - javascript

i have this node js script:
var EventEmitter = require('events').EventEmitter,
util = require('util');
var pfioObject = function () {
this.init = function () {
console.log("started server");
};
this.deinit = function () {
console.log("stopped server");
};
this.read_input = function () {
return 0;
};
};
console.log(util.inspect(EventEmitter, false, null)); //<--- this shows no method emit either
var pfio = new pfioObject();
var pfioServer = function () {
this.prev_state = 0;
this.start = function () {
pfio.init();
this.watchInputs();
};
this.stop = function () {
pfio.deinit();
};
}
util.inherits(pfioServer, EventEmitter);
// add some event emitting methods to it
pfioServer.prototype.watchInputs = function () {
var state = pfio.read_input();
if (state !== this.prev_state) {
this.emit('pfio.inputs.changed', state, this.prev_state);
this.prev_state = state;
}
setTimeout(this.watchInputs, 10); // going to put this on the event loop next event, more efficient
};
// export the object as a module
module.exports = new pfioServer();
For some reason the node error says that there is no such object as emit, i have done npm install events to see if that will fix it, it didn't. I'm unsure as to why I'm getting this error.
I think somewhere along my code there is an error but I can't see anything.
To run this code I have another script which does this:
var pfioServer = require('./pfioServer'),
util = require('util');
console.log(util.inspect(pfioServer, false, null)); //<--- this line shows the pfioServer with out the prototype function watchInputs
pfioServer.start();
EDIT
I think I may have missed out on some vital bits of code around the event emitter stuff, am looking into instantiation of the event emitter class
Slight Change
So instead of EventEmitter being inherited, i instantiated it by doing var emitter = new EventEmitter()
Then after that I got errors in the util.inspect about the object having to be an object or be null.
No success yet.

I found two things that had to be changed for the first code-block to run without errors:
Explicitly instantiate events.EventEmitter():
var events = require('events'); var EventEmitter = new events.EventEmitter();
Change the call to util.inherits:
util.inherits(pfioServer, events.EventEmitter);
The last thing to make the server run is what robertklep wrote: fix binding in setTimeout()
setTimeout(this.watchInputs.bind(this), 10);

The reason is this line:
setTimeout(this.watchInputs, 10);
When the timeout is triggered and this.watchInputs is called, it has lost its context.
You need to explicitly set the context object (in other words, what this inside the method should point to) for that call by using bind:
setTimeout(this.watchInputs.bind(this), 10);

console.log(util.inspect(EventEmitter, false, null));
// this shows no method emit either
The EventEmitter constructor function does not have such a method. EventEmitter.prototype has. To print the (non-enumerable) .prototype property, you can use util.inspect(EventEmitter, {showHidden: true}) as #Emissary mentioned in the comments.
// this line shows the pfioServer with out the prototype function watchInputs
console.log(util.inspect(pfioServer, false, null));
Yes. util.inspect does not show inherited properties, only those apparent on the pfioServer instance itself.
setTimeout(this.watchInputs, 10);
// going to put this on the event loop next event, more efficient
I'd rather say it prevents an infinite loop… However, this also destroys the this context in the next invokation, which is no more your pfioServer instance. See How to access the correct `this` context inside a callback?
In your case however, I don't see the necessity of using a constructor and inheriting from a prototype anyway. You're just exporting a singleton object, which you simply could instantiate with an object literal and reference by its variable name.

Related

Why can’t I access a property on “this” in a class via its prototype?

I wrote this class and have set up an array property for it. Then, I want to add an item to this array.
However, when I try to do it, I get the error “Uncaught TypeError: Cannot read property push of undefined”.
Isn’t this possible?
class test {
constructor() {
this.myArray = [];
}
myMethod() {
this.myArray.push("ok");
}
};
console.log(test.prototype.myMethod());
That’s not how classes are used. You need to instantiate test first, by using new test(). The constructor was never called in your case, so this.myArray was never defined.
This is the only way this can work:
let testInstance = new test();
testInstance.myMethod();
This way, the constructor is called and there will be no error.
Of course, next you’ll need some way of retrieving your array, in order to see the effect.
try to create the instance first. See the code I've commented it in details
test.prototype = {
constructor: test,
myMethod: function() {
this.myArray.push("ok");
}
};
var test = function(){
this.myArray = [];
}
test.prototype = { // add our custom constructor and custom methods
constructor: test,
myMethod: function() {
this.myArray.push("ok");
}
};
var myVar = new test(); // create new instance of test
myVar.myMethod(); // run custom method to push val
console.log( myVar.myArray );
You need to initiate your class test first.
var t = new test();
For your information:
console.log(test.prototype.myMethod());
will give you "undefined". Try e.g. :
var t = new test();
t.myMethod();
console.log(t.myArray);
to get output similar to this:
Array [ "ok" ]

Adding properties dynamically to node module

I am experimenting with different ways to code a Node.js module and tried this:
game.js
var board = require('./board'),
player = require('./player');
// setting module.exports to a function constructor so I can make instances of this node module from my test
var game = module.exports = function(){};
// dynamically add properties and set their default values
// I don't think I need to use any prototypes here right?
// And yes I realize I could use ES6 classes with an explicit constructor but that's a suggestion we can put on the side for now...
game.initialize = function(){
game.started = false;
game.status = 'not started';
game.board = board.create();
return game;
};
game.start = function(){
game.started = true
};
game-test.js
let chai = require('chai'),
should = chai.should(),
game = require('../src/game');
describe('Game - Initial State', () => {
var newGame;
beforeEach((done) => {
newGame = new game().initialize;
done();
});
it('should contain a new board to play on', () => {
should.exist(newGame.board);
});
...
I'm getting the error "Cannot read property 'board' of undefined"
If I remove the .initialize() I get an instance of game but then no properties. I'm not sure if this is even a good pattern but first would like to know what I'm doing wrong here. And then any additional suggestions I'm open to hearing.
Game.initialize is a function.
In your test your are not calling the function, so your variable newGame is just a ref to Game.initialize instead of a Game instance
// your line
newGame = new game().initialize;
// should be
newGame = new game().initialize();
Edit: Also, you may want to use this instead of game in your initialize() function.

Integrate EventEmitter in Object construtor to use in prototype methods

I have the following, strange problem:
I wrote a "Class" Game. This Class has a constructor and one prototype method. I want the whole construct to be an EventEmitter. So I thought I could just inherit the event.EventEmitter for my constructor.
It looked first as follows:
game.js
var EventEmitter = require('events').EventEmitter;
var util = require('util');
/*
Game factory
*/
function Game(catalogue, speed) {
//EventEmitter.call(this);
this.catalogue = catalogue || null;
this.speed = speed || 10;
}
Game.prototype.listen = function(){
var self = this;
setInterval(function(){
self.emit('init', 0);
}, 500);
}
util.inherits(Game, EventEmitter);
module.exports = Game;
I use socket.io to connect to the client. In my main socket routine I use the following code to start a new game (instantiate)
controller.js
socket.on('startGame', function(){
var myGame = new Game('default', 10);
myGame.init();
myGame.on('init', function(status){
console.log('Did start with status code: ', status);
});
};
This does not work as expected.Error is:
Missing error handler on `socket`.
TypeError: undefined is not a function
at Socket.<anonymous>
When I use the emit event in the constructor, it works (without myGame.listen() in the console.js, of course):
function Game(catalogue, speed) {
//EventEmitter.call(this);
this.catalogue = catalogue || null;
this.speed = speed || 10;
var self = this;
setInterval(function(){
self.emit('init', (Math.random()*10).toFixed(0));
}, 500)
}
So what is wrong here?
Note that I don't need
EventEmitter.call(this);
in the constructor in the second example.
But independent from commenting this out or leaving it in, this downs change anything.
Why do I need this at all? Do I?
Maybe you can help. Kind regard.
Martin
You have to move your util.inherits(Game, EventEmitter); to before you start adding functions to your prototype. The util.inherits() meddles with the prototype, so anything placed on it before then is lost.
Additionally, when you inherit from another object (like EventEmitter), you really should call the parent constructor (EventEmitter.call(this)) because it may need to do some initialization of its own.
Updated example with Node.js v11.12.0
const EventEmitter = require('events');
module.exports = class Game extends EventEmitter {
constructor(catalogue, speed) {
super();
this.catalogue = catalogue || null;
this.speed = speed || 10;
}
listen() {
setInterval(() => {
self.emit('init', 0);
}, 500);
}
};
let myGame = new Game('default', 10);
myGame.listen();
myGame.on('init', status => {
console.log('Did start with status code: ', status);
});
Some neat new stuff here.
Don't need require('events').EventEmitter suffix part anymore. It is still available for backwards compatibility.
Can use class and extends.
Can use arrow functions in the setInterval which implicitly binds to this instead of needing to map this to self.

Prototype function overriden by other "class"

I have the following inputModel:
var UserCreateInputModel = function(req) {
...
this.password = req.body.password;
this.repeatPassword = req.body.repeatPassword;
...
console.log(this.password !== this.repeatPassword);
this.validate();
};
UserCreateInputModel.prototype = InputModel;
UserCreateInputModel.prototype.validate = function() {
console.log('Validating...');
if(this.password !== this.repeatPassword) throw new Error('Passwords are not equal!');
};
module.exports = UserCreateInputModel;
In my test I would like to test if the exception was thrown (using node's assert module):
//Act
assert.throws(function() {
new UserCreateInputModel(req);
}, Error);
Somehow the exception is just not thrown. My console output from the constructor is "this".
On the console I don't see the output "Validating".
I guess this is some JavaScript pitfall or something like that (about this) but I'm just not getting the error ...
Update
I have another inputModel in another file. This "inherites" from InputModel too. So it seems UserCreateInputModel.prototype.validate is overridden in the other inputModel. Still don't get it ...
This line:
UserCreateInputModel.prototype.validate = function() {
console.log('Validating...');
if(this.password !== this.repeatPassword) throw new Error('Passwords are not equal!');
};
is modifying the InputModel object. If you have two different types "inheriting" from InputModel with what you have here, and they both have validate methods, then one is overwriting the other.
To properly inherit from InputModel, use Object.create():
UserCreateInputModel.prototype = Object.create(InputModel.prototype);
And then call the parent constructor from your child constructor:
var UserCreateInputModel = function(req) {
InputModel.call(this, <arguments>);
This way, when you modify UserCreateInputModel.prototype, you will only be modifying UserCreateInputModel.prototype and not anything else.
UserCreateInputModel.prototype = InputModel is not how you do inheritance. Who taught you this???!!!
It's:
after the constructor, util.inherits(UserCreateInputModel, InputModel) (where util is require('util')), and
inside the constructor, calling InputModel.apply(this, arguments); or InputModel.call(this, <explicit list of input model ctr args>).
Get back with another EDIT if it still persists.

JS and methods in class emulation

I am new to this so I'll try to be as detailed as possible.
I am creating a JS class using functions.
function Bandstar(p, id)
{
var numberOfSides, Xcenter, Ycenter;
var canvas;
var circlesInt;
var linesInt;
var lines;
var linesInt2;
var linesMidToEdge;
.....
When it comes to methods, I just declare them like this:
this.IAset = function(a)
{
for (var i =0; i<= this.numberOfSides-1;i++)
{
if (parseInt(a[i]) == a[i])
this.circles[i].value = a[i];
else
return false;
}
this.IArepaint();
return true
}
and that's pretty much it.
The problem now is that, when I am creating a specific method:
this.moveFunc = function(e)
{
var p = e.target;
this.IAmove(p);
};
with the method IAmove being declared as follows:
this.IAmove = function(p)
{
var m = (p.oTop - this.Ycenter ) / (p.oLeft - this.Xcenter);
var linea = m * ( p.left - p.oLeft) + p.oTop;
var ejeX = p.left;
...
}
The compiler just keeps throwing this error:
Uncaught TypeError: Object function (e) { var p = e.target; this.IAmove(p); } has no method 'IAmove'
So, the thing is that I am declaring moveFunc as a function but then when I try to get to use this property, it doesn't actually use the instance of the class above it, (Bandstar), but of itself (and obviously moveFunc doesn't have a method called IAmove, the class on which it is being created is)...
I thought this was just like it worked, but I must not be getting the concept of heritage and class morphology in JS right.
How can I access a method in a class from another method inside that same class? If I just write IAmove(p) it will just say the method IAmove() is undefined (because it isn't, it's part of the Bandstar namespace.
I know it must be something stupid that I'm not seeing. Any suggestions?
The context inside your function may change based on your call. So this could not be the original object.
You should add a private var like:
function Bandstar(p, id)
{
var numberOfSides, Xcenter, Ycenter;
var canvas;
var that = this; // add this line
and use it when you try to call function (or get properties) of original object
this.moveFunc = function(e)
{
var p = e.target;
that.IAmove(p); // change this line
};
for be sure to point to original object.
EDIT: According with comments you can read more infos in Stuart's answer
You probably wants to add these methods to your Bandstar prototype.
function Bandstar(p, id)
{
// ...
}
Bandstar.prototype.IAset = function(a)
{
// ...
}
Bandstar.prototype.moveFunc = function(e)
{
var p = e.target;
this.IAmove(p);
};
This way your methods keep the Bandstar context, and this will remain Bandstar instance reference.
Have a look at Object.prototype reference
Assuming all of those methods are defined in the constructor the syntax is correct. The following fiddle illustrates it working, the code is based on a simplified version of your code...
function Test() {
this.move = function(p) {
document.write("Moved to: " + p);
};
this.another = function(e) {
this.move(e.target);
};
}
var test = new Test();
test.another({target: "The moon"});
The cause of the issues is likely to be one of two three things:
How the method moveFunc is called
When the method moveFunc is called
How the method IAmove is called (it may not be the moveFunc function that is causing that error).
The this keyword will reference the scope of the function which is typically the owner of the method...
var bandstar = new Bandstar(p, id);
bandstar.moveFunc(e); // this should be bandstar
The only reasons that might not be the case is if you are explicitly binding the moveFunc function to another object or a more common situation is that the function is being called without being attached to the owner...
var bandstar = new Bandstar(p, id);
var moveFunc = bandstar.moveFunc(e);
moveFunc(e); // this will now be window
The this keyword will default to window if the owner is detached from it. You can bind the function using.
var bandstar = new Bandstar(p, id);
var moveFunc = bandstar.moveFunc(e);
moveFunc.bind(bandstar);
moveFunc(e); // this will now be bandstar again
In the second issue both methods must be defined in the constructor before the moveFunc function can be called
this.moveFunc = function(e) { ... }
this.moveFunc(e); // Will throw an error that IAmove does not exist in the object
this.IAmove = function(p) { ... }
You can log the this object using console.log(this); to find out what it is.
It looks as though from your error that you are trying to call IAmove on the moveFunc function. For this error to be caused you would need to have called moveFunc with itself as the owner or the bound object... Which is not a particularly likely.
I have a hunch that the error may not actually be related to the this.IAmove(p); call in the moveFunc as assumed. Post the stack trace and we can use that to find where the error occurred.

Categories

Resources