The event handler in the constructor behaves differently than the event handler from the constructor

I have two instances of an object that extends an EventEmitter and listens for an event called finish . If I install an event handler outside the constructor, everything works as expected. Each instance hears the occurrence of finish , which it causes. But if I install an event handler inside the constructor, only the instance created by the second hears and responds to the event, or so it seems.

Here is the code:

 var util = require('util'); var EventEmitter = require('events').EventEmitter; var fs = require('fs'); var NEXT_ID = 0; var MyEmitter = function() { EventEmitter.call(this); this.id = NEXT_ID; NEXT_ID++; console.log('CREATED EMITTER WITH ID:', this.id) self = this; this.on('finish', function() { console.log('FINISH EVENT . CONSTRUCTOR LISTENER .', 'LISTENER ID:', self.id, '. ORIGINATOR ID:', this.id); }); }; util.inherits(MyEmitter, EventEmitter); var setFinishListener = function(emitter) { emitter.on('finish', function() { console.log('FINISH EVENT . NON-CONSTRUCTOR LISTENER .', 'LISTENER ID:', emitter.id, '. ORIGINATOR ID:', this.id); }); } var emitter0 = new MyEmitter(); var emitter1 = new MyEmitter(); setFinishListener(emitter0); setFinishListener(emitter1); emitter0.emit('finish'); emitter1.emit('finish'); // The following is logged to the console: // FINISH EVENT . CONSTRUCTOR LISTENER . LISTENER ID: 1 . ORIGINATOR ID: 0 // FINISH EVENT . NON-CONSTRUCTOR LISTENER . LISTENER ID: 0 . ORIGINATOR ID: 0 // FINISH EVENT . CONSTRUCTOR LISTENER . LISTENER ID: 1 . ORIGINATOR ID: 1 // FINISH EVENT . NON-CONSTRUCTOR LISTENER . LISTENER ID: 1 . ORIGINATOR ID: 1 

Please note that the LISTENER ID for the version of the event handler that is configured inside the MyEmitter constructor always belongs to the second instantiated instance, making it seem like this instance always captures the event first, and for some reason the first instantiated instance never started this event handler.

Two facts that I assume, I understand correctly:

  • this in the event handler should always be the object that emitted the event.
  • this in the constructor should always be the object returned by the constructor (because it is called with new ).

If both of them are true, I do not know what else I do not understand, which leads to the manifested behavior.

Another thing made me wonder: should the event be β€œheard” by the same EventEmitter that selected the event? This is what I thought, and of course, this is the most common use case. But if this is not a limitation, then how, for example, the click event on a button does not cause click handlers for all other buttons?

+5
source share
1 answer

The problem is that you are not using var self = this; to bind the self variable to the Emitters scope. When you exit var , Javascript will raise the variable in scope until it finds the matching variable name declared with var . Since you never announced this, self will be posted to the global scope, and therefore, each emitter will be created with the same link.

Adding var self = this will solve the problem. You can also add use strict to catch these problems, as this will not allow you to declare a variable without using var .

+6
source

All Articles