Search code examples
node.jseventseventemitter

Node.js delegating functions to an imported module


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?


Solution

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