1

When I search for custom events on JavaScript classes, I get a lot of old or incomplete results. MDN shows a custom event off of a dom element. Stackoverflow's top result is almost ten years old and it uses the pre-ES6 syntax.

Is there a way of doing something like:

class Dog
{
  constructor(name)
  {
    this.name = name;
  }
  
  //something to expose bark event
  
}

const buddy = new Dog('buddy');
buddy.addEventListener("bark", function(e) {
  console.log(`${this.name} barked!`);
});
dholm
  • 13
  • 3
  • 1
    unsure how a class has event listeners. Not sure what you are expecting to happen. You probably just want to implement methods. – epascarello Jul 28 '21 at 17:27
  • You can extend `EventEmitter` which can provide you the event handling functionalities. Check more https://nodejs.org/api/events.html#events_class_eventemitter – Sajeeb Ahamed Jul 28 '21 at 17:33
  • 1
    what do you mean by custom events? why not simply add a method to your class and call it when you want to trigger it? – Rod911 Jul 28 '21 at 17:41
  • because I want to allow clients to listen in on when the bark event happens. – dholm Jul 28 '21 at 17:56
  • JavaScript is not .net or C#. It doesn't define events in object interfaces. – Bergi Jul 28 '21 at 20:29

3 Answers3

3

But in your snippet, you wanted to have dog.bark(), in that case see below

class Dog {
  addEventListener(method,callback) {
     this[method] = callback;
  }

  removeEventListener (method) {
      delete this[method];
   }
}

The above will work as

const dog = new Dog();

dog.addEventListener('bark', ()=>console.log("bow"));
dog.bark() // logs => bow

dog.addEventListener('somethingsomething', ()=>{ /*do something*/ })

dog.removeListener('bark');

We can implement tiny class as EventEmitter pattern

class Dog {
   constructor() {
      this.listeners = {};
   }

   emit(method, payload = null) {
      const callback = this.listeners[method];
      if(typeof callback === 'function'){
          callback(payload);
      }
  }

  addEventListener(method,callback) {
     this.listeners[method] = callback;
  }

  removeEventListener (method) {
      delete this.listeners[method];
   }
}

And we can use this class like this

const dog = new Dog();

dog.addEventListener('bark',(customSound)=>console.log(customSound || "Bow Bow"));

dog.addEventListener('eat', ()=>console.log("eating yum yum") );

dog.emit('bark') // logs => Bow Bow
dog.emit('bark', 'i can talk humans') // logs => i can talk humans
dog.emit('eat');

dog.removeEventListener('bark');

Note: it's raw implementation, not production ready code. Thanks.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
varaprasadh
  • 488
  • 5
  • 13
  • wow man, you would believe how I've searched for something like this... all implementations I've found so far required DOM elements.. thank you!!! – zergski Dec 16 '21 at 08:31
1

There are no events with a class. You can implement something that registers functions and you can call them when the method is triggered. Basic idea:

class Animal {
  #registered = {};
  
  constructor(name)
  {
    this.name = name;
  }  
  
  addEventListener(name, callback) {
    if (!this.#registered[name]) this.#registered[name] = [];
    this.#registered[name].push(callback);
  }
  triggerEvent(name, args) {
     this.#registered[name]?.forEach(fnc => fnc.apply(this, args));
  }
}


class Dog extends Animal
{
  constructor(name)
  {
    super(name);
  }
  
  bark(){
    console.log('bark was called');
    this.triggerEvent('bark');
  }

  eat(what){
    console.log('eat was called', what);
    this.triggerEvent('eat', [what]);
  }

}

const buddy = new Dog('buddy');
buddy.addEventListener("bark", function() {
  console.log(`${this.name} barked!`);
});
buddy.addEventListener("eat", function(item) {
  console.log(`${this.name} ate a ${item}!`);
});
buddy.bark();
buddy.eat('bone');
epascarello
  • 204,599
  • 20
  • 195
  • 236
  • 1
    bummer what? You are not creating DOM elements – epascarello Jul 28 '21 at 17:58
  • 1
    im looking at this from the C# perspective: https://www.tutorialsteacher.com/csharp/csharp-event to me, events are events, it shouldn't matter if it is or isn't from the dom – dholm Jul 28 '21 at 18:27
  • 1
    @varaprasadh Same thing I have..... issue is your code only handles one event listener being attached.... – epascarello Jul 28 '21 at 19:44
  • @varaprasadh You have an `addEventListener` and a `emit`..... I have `addEventListener` and `triggerEvent` Not sure how that is any different than mine. I just chose to make a bark() and not call `triggerEvent` (your emit) directly.... The code is literally the same thing. – epascarello Jul 29 '21 at 14:45
  • @varaprasadh It is the same thing.... not sure what you think is different. I can swap `triggerEvent` to be named `emit` and it will basically be the same thing. Only difference is I allow multiple events to be added, you have one. – epascarello Jul 29 '21 at 17:44
  • https://jsfiddle.net/epascarello/dwob4esf/ <-- That I some how can change my method to "emit" and used your code that creates the instance of dog. So how is it not similar other than I did not make the removeEventListener. – epascarello Jul 30 '21 at 12:52
0

Extend EventTarget class to get all event functions:

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/EventTarget

Fernando Bonafé
  • 121
  • 1
  • 1
  • 6