0

I'm trying to associate each instance of a class with an event emitter. I'm trying the following:

const events = require("events");
const eventEmitter = new events.EventEmitter();

class Camera {
    constructor(ip) {
        this.ip = ip;

        eventEmitter.on("recordVideo", function() {
            this.recordClip();
        });
    }

    recordClip() {
        console.log("record " + this.ip);
    }
}

var cam = new Camera("0.0.0.0");
eventEmitter.emit("recordVideo");

But I get back:

TypeError: this.recordClip is not a function

How can I have each instance of my class listen for the event?

Philip Kirkbride
  • 21,381
  • 38
  • 125
  • 225
  • Why not just use the code from [the answer you've already gotten](https://stackoverflow.com/a/45601755/1048572)? – Bergi Aug 10 '17 at 03:28
  • @bergi sorry, I just copied and pasted my function call into the constructor. I didn't notice the bind change that was made. – Philip Kirkbride Aug 10 '17 at 03:37

2 Answers2

1

It's because the context in the callback function is not referencing what you expect it to. Add an arrow function.

const events = require("events");
const eventEmitter = new events.EventEmitter();

class Camera {
   constructor(ip) {
     this.ip = ip;

      eventEmitter.on("recordVideo", () => {
        this.recordClip();
      });
   }

   recordClip() {
      console.log("record " + this.ip);
   }
}

   var cam = new Camera("0.0.0.0");
   eventEmitter.emit("recordVideo");

Here is some docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

halfer
  • 19,824
  • 17
  • 99
  • 186
miguelsolano
  • 519
  • 3
  • 11
1

Your issue here is that this is in the context of the event emitter, not the class. So, eventEmitter does not have recordClip as a method. You need to either lexically bind your callback with an arrow function:

(Personally, I think this is the best, and most modern/readable way to do this)

eventEmitter.on("recordVideo", () => {
    this.recordClip();
});

Or, you need to bind the proper scope:

eventEmitter.on("recordVideo", function() {
    this.recordClip();
}).bind(this);

Or you can make a reference to this via the self methodology:

class Camera {
    constructor(ip) {
        this.ip = ip;
        const self = this; //assign this to self
        eventEmitter.on("recordVideo", function() {
            self.recordClip(); //use self, not this here
        });
    }

    recordClip() {
        console.log("record " + this.ip);
    }
}
Sterling Archer
  • 22,070
  • 18
  • 81
  • 118