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?
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?
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:
Maga Zandaqo has an excellent detailed guide here: https://medium.com/@zandaqo/eventtarget-the-future-of-javascript-event-systems-205ae32f5e6b
MDN has some documentation: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
Polyfill for Safari and other incapable browsers: https://github.com/ungap/event-target
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');
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
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
I ended up using this:
export let createEventEmitter = () => {
let callbackList: (() => any)[] = []
return {
on(callback: () => any) {
callbackList.push(callback)
},
emit() {
callbackList.forEach((callback) => {
callback()
})
},
}
}
2022 update: The BroadcatsChannel may provide a solution.
https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API
I have created an npm package that do the same. You can use in Javascript or Typescript event-emitter
Example
import { EventEmitter } from 'tahasoft-event-emitter';
const onStatusChange = new EventEmitter();
function updateStatus() {
// ...
onStatusChange.emit();
}
// somewhere else, we want to add a listener when status change
onStatusChange.add(() => {
// ...
});
A very basic solution
function createEventEmitter() {
const events = {}
return {
on: (name, listener) => {
const listeners = events.hasOwnProperty(name)
? events[name]
: (events[name] = [])
listeners.push(listener)
},
emit: (name, ...params) => {
const listeners = events[name] || []
listeners.forEach((listener) => {
listener(...params)
})
},
}
}
const emitter = createEventEmitter()
emitter.on('myevent', (a, b) => {
console.log(a, b)
})
emitter.emit('myevent', 1, 2)
I like the answer from Alparslan above. Here's one that uses the browser CustomEvent.
let EventEmitter = (function () {
let elem = document.createElement("div")
return {
on: function (name, cb) {
elem.addEventListener(name, (e) => cb(e.detail), false )
},
emit: function (name, data) {
elem.dispatchEvent(new CustomEvent(name, {detail: data}))
}
}
})()
Here is a complete code for implementing the EventEmitter class that can be used both in the browser and in node applications. However, I recommend modifying & testing it well before using it.
import { EventEmitter as NodeEventEmitter } from 'events';
type Callback = (params: any) => void | Promise<void>;
const wrapFunction =
(fn: Callback): Callback =>
(params: CustomEvent) =>
fn(params.detail);
export class InBrowserEventEmitter extends EventTarget {
private _listeners: Record<string, [key: Callback, value: Callback][]> = {};
private maxListeners = Number.MAX_SAFE_INTEGER;
public on(eventName: string, fn: Callback) {
this.addEventListener(eventName, fn);
return this;
}
public once(eventName: string, fn: Callback) {
const onceCallback = async (params: CustomEvent) => {
await fn(params);
this.off(eventName, onceCallback);
};
return this.on(eventName, onceCallback);
}
public off(eventName: string, fn: Callback) {
this.removeEventListener(eventName, fn);
return this;
}
public emit(eventName: string, params: unknown) {
const event = new CustomEvent(eventName, { detail: params });
return super.dispatchEvent(event);
}
public listenerCount(eventName: string): number {
const eventListeners = this._listeners[eventName];
return eventListeners ? eventListeners.length : 0;
}
public listeners(eventName: string): Callback[] {
return this._listeners[eventName].map(value => value[0]) || [];
}
public eventNames(): string[] {
return Object.keys(this._listeners);
}
public removeAllListeners() {
this._listeners = {};
return this;
}
public setMaxListeners(maxListeners: number) {
this.maxListeners = maxListeners;
return this;
}
public getMaxListeners(): number {
return this.maxListeners;
}
public addEventListener(eventName: string, fn: Callback) {
const wrappedFn = wrapFunction(fn);
super.addEventListener(eventName, wrappedFn);
if (!this._listeners[eventName]) {
this._listeners[eventName] = [];
}
this._listeners[eventName].push([fn, wrappedFn]);
}
public removeEventListener(eventName: string, fn: Callback) {
const eventListeners = this._listeners[eventName];
if (eventListeners) {
const index = eventListeners.findIndex(item => item[0] == fn);
if (index !== -1) {
super.removeEventListener(eventName, eventListeners[index][1]);
eventListeners.splice(index, 1);
}
}
}
}
// eslint-disable-next-line import/no-mutable-exports
export let EventEmitter: typeof NodeEventEmitter;
if (typeof window === 'undefined') {
EventEmitter = NodeEventEmitter;
} else {
// Fallback for the browser environment
EventEmitter = InBrowserEventEmitter as unknown as typeof NodeEventEmitter;
}
Written with help from an AI Language Modle :-)
You need a JavaScript library, like this https://github.com/Olical/EventEmitter?
Node gained a native EventTarget in Node 15 (Oct 2020;) this question no longer applies
https://nodejs.org/api/events.html#eventtarget-and-event-api