59

It is so easy to use eventEmitter in node.js:

var e = new EventEmitter();
e.on('happy', function(){console.log('good')});
e.emit('happy');

Any client side EventEmitter in browser native?

Suraj Rao
  • 28,850
  • 10
  • 94
  • 99
Xin
  • 28,603
  • 13
  • 79
  • 74

6 Answers6

98

In modern browsers, there is EventTarget.

class MyClass extends EventTarget {
  doSomething() {
    this.dispatchEvent(new Event('something'));
  }
}

const instance = new MyClass();
instance.addEventListener('something', (e) => {
  console.log('Instance fired "something".', e);
});
instance.doSomething();

Additional Resources:

Brad
  • 152,561
  • 47
  • 332
  • 504
11

There is a NPM package named "events" which makes you able to make event emitters in a browser environment.

const EventEmitter = require('events')
 
const e = new EventEmitter()
e.on('message', function (text) {
  console.log(text)
})
e.emit('message', 'hello world')

in your case, it's

const EventEmitter = require('events')

const e = new EventEmitter();
e.on('happy', function() {
    console.log('good');
});
e.emit('happy');
NanderTGA
  • 5
  • 1
  • 5
Amir Gorji
  • 1,863
  • 18
  • 22
  • 1
    OP is looking for a working on a native implementation on a browser not requiring a npm package. – Ivan Oct 09 '20 at 07:42
  • 1
    @Ivan SO answers aren't just for the OP. This is the answer I was looking for, and looking at the votes, other people too. I want the same code to work in both environments. – Inigo Apr 10 '22 at 03:34
7

This is enough for given case.

class EventEmitter{
    constructor(){
        this.callbacks = {}
    }

    on(event, cb){
        if(!this.callbacks[event]) this.callbacks[event] = [];
        this.callbacks[event].push(cb)
    }

    emit(event, data){
        let cbs = this.callbacks[event]
        if(cbs){
            cbs.forEach(cb => cb(data))
        }
    }
}

Update: I just published little bit more evolved version of it. It is very simple yet probably enough: https://www.npmjs.com/package/alpeventemitter

Alparslan
  • 71
  • 1
  • 2
  • Typescript: `callbacks: { [s: string]: ((...args: any[]) => any)[] }` – Mathieu CAROFF Jan 04 '20 at 11:43
  • 1
    This will result in out-of-order event handling when a event handler emits another event. You probably want to call the callbacks in emit after it returns, with setTimeout. Or put the events in a queue. – Vinicius Fortuna Jul 28 '21 at 16:39
5

Create a customized event in the client, and attach to dom element:

var event = new Event('my-event');

// Listen for the event.
elem.addEventListener('my-event', function (e) { /* ... */ }, false);

// Dispatch the event.
elem.dispatchEvent(event);

This is referred from: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events Thanks Naeem Shaikh

Xin
  • 28,603
  • 13
  • 79
  • 74
  • 8
    This only works on HTML elements, the question is how to make it work on an object like you can do in Node. – Kokodoko Sep 23 '19 at 12:00
3

I ended up using this:

export let createEventEmitter = () => {
   let callbackList: (() => any)[] = []

   return {
      on(callback: () => any) {
         callbackList.push(callback)
      },
      emit() {
         callbackList.forEach((callback) => {
            callback()
         })
      },
   }
}

Mathieu CAROFF
  • 890
  • 11
  • 17
-3

You need a JavaScript library, like this https://github.com/Olical/EventEmitter

JiangangXiong
  • 2,126
  • 1
  • 10
  • 14