When I search for custom events on JavaScript classes, I get a lot of old or inplete 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!`);
});
When I search for custom events on JavaScript classes, I get a lot of old or inplete 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!`);
});
Share
Improve this question
asked Jul 28, 2021 at 17:25
dholmdholm
231 silver badge3 bronze badges
5
- 1 unsure how a class has event listeners. Not sure what you are expecting to happen. You probably just want to implement methods. – epascarello Commented Jul 28, 2021 at 17:27
-
You can extend
EventEmitter
which can provide you the event handling functionalities. Check more nodejs/api/events.html#events_class_eventemitter – Sajeeb Ahamed Commented Jul 28, 2021 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 Commented Jul 28, 2021 at 17:41
- because I want to allow clients to listen in on when the bark event happens. – dholm Commented Jul 28, 2021 at 17:56
- JavaScript is not or C#. It doesn't define events in object interfaces. – Bergi Commented Jul 28, 2021 at 20:29
4 Answers
Reset to default 4But 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.
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');
Extend EventTarget class to get all event functions:
https://developer.mozilla/en-US/docs/Web/API/EventTarget/EventTarget
@varaprasadh approach helped me get started, but lacked accumulating multiple events. Modified to also allow remove listener that functions similar to on DOM events to get rid of one based on callback.
class Dog {
constructor() {
this.listeners = {};
}
emit(method, payload = null) {
if (this.listeners.hasOwnProperty(method)) {
const callbacks = this.listeners[method];
for (let [key, callback] of Object.entries(callbacks)) {
if (typeof callback === 'function') {
callback(payload);
}
}
}
}
addEventListener(method, callback) {
if (!this.listeners.hasOwnProperty(method)) {
this.listeners[method] = {}
}
this.listeners[method][callback] = callback;
}
removeEventListener(method, callback) {
if (this.listeners.hasOwnProperty(method)) {
delete this.listeners[method][callback];
}
}
}