0

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?

ahjmorton
  • 965
  • 1
  • 5
  • 18
  • how do you "register" your callback with "on"? – robkuz Apr 13 '13 at 13:57
  • @robkuz The same way I would register a callback with any EventEmitter so if my module was called "myModule" I would register it with myModule.on("event", function() { console.log("called");}); – ahjmorton Apr 13 '13 at 14:27

1 Answers1

4

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);
Sebastian vom Meer
  • 5,005
  • 2
  • 28
  • 36
  • Ahhh I didn't realise that using exports causing a binding to the "this" parameter. That is where I was getting stuck. Marking as answered. – ahjmorton Apr 13 '13 at 15:52