Callum Linington
Callum Linington

Reputation: 14417

EventEmitter has no emit

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.

Upvotes: 0

Views: 739

Answers (3)

grebneke
grebneke

Reputation: 4494

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);

Upvotes: 1

Bergi
Bergi

Reputation: 665536

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.

Upvotes: 1

robertklep
robertklep

Reputation: 203519

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);

Upvotes: 1

Related Questions