0

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.

Alex
  • 11,115
  • 12
  • 51
  • 64
Callum Linington
  • 14,213
  • 12
  • 75
  • 154

3 Answers3

1

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);
robertklep
  • 198,204
  • 35
  • 394
  • 381
1

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);
Community
  • 1
  • 1
grebneke
  • 4,414
  • 17
  • 24
  • could you elaborate more on the bind in the setTimeout, i was thinking of changing it to the event loop next – Callum Linington Feb 04 '14 at 20:38
  • The code run by `setTimeout()` (`watchInputs`) contains `this`. `bind` makes the code reference the correct local `this` instead of the global object. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#With_setTimeout – grebneke Feb 04 '14 at 20:47
1
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.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • It does if it's used correctly :) `util.inspect(obj, {showHidden: true})` [*docs*](http://nodejs.org/api/util.html#util_util_inspect_object_options) – Emissary Feb 04 '14 at 19:06
  • @Emissary: Still nope. I couldn't find good docs about it, so I've looked it up [in the source code](https://github.com/joyent/node/blob/657cd2c4e5940d32883a6791be41978a6d07afb8/lib/util.js#L238): `showHidden` does only activate non-enumerable properties, but it's still only the own ones. – Bergi Feb 04 '14 at 19:09
  • it will happily print the the prototype on the EventEmitter constructor is what I was getting at - as per OP use. – Emissary Feb 04 '14 at 19:11