-
-
Save rafpro/9c3d5807d4a830e9284ed24c0a2af1bc to your computer and use it in GitHub Desktop.
A very simple EventEmitter in pure JavaScript (suitable for both node.js and browsers).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class EventEmitter{ | |
constructor(){ | |
this.events = {}; | |
} | |
_getEventListByName(eventName){ | |
if(typeof this.events[eventName] === 'undefined'){ | |
this.events[eventName] = new Set(); | |
} | |
return this.events[eventName] | |
} | |
on(eventName, fn){ | |
this._getEventListByName(eventName).add(fn); | |
} | |
once(eventName, fn){ | |
const self = this; | |
const onceFn = function(...args){ | |
self.removeListener(eventName, onceFn); | |
fn.apply(self, args); | |
}; | |
this.on(eventName, onceFn); | |
} | |
emit(eventName, ...args){ | |
this._getEventListByName(eventName).forEach(function(fn){ | |
fn.apply(this,args); | |
}.bind(this)); | |
} | |
removeListener(eventName, fn){ | |
this._getEventListByName(eventName).delete(fn); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class EventEmitter { | |
constructor() { | |
this.events = {}; | |
} | |
on(event, listener) { | |
if (typeof this.events[event] !== 'object') { | |
this.events[event] = []; | |
} | |
this.events[event].push(listener); | |
return () => this.removeListener(event, listener); | |
} | |
removeListener(event, listener) { | |
if (typeof this.events[event] === 'object') { | |
const idx = this.events[event].indexOf(listener); | |
if (idx > -1) { | |
this.events[event].splice(idx, 1); | |
} | |
} | |
} | |
emit(event, ...args) { | |
if (typeof this.events[event] === 'object') { | |
this.events[event].forEach(listener => listener.apply(this, args)); | |
} | |
} | |
once(event, listener) { | |
const remove = this.on(event, (...args) => { | |
remove(); | |
listener.apply(this, args); | |
}); | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Listener = (...args: any[]) => void; | |
interface IEvents { [event: string]: Listener[]; } | |
export class EventEmitter { | |
private readonly events: IEvents = {}; | |
public on(event: string, listener: Listener): () => void { | |
if (typeof this.events[event] !== "object") { | |
this.events[event] = []; | |
} | |
this.events[event].push(listener); | |
return () => this.removeListener(event, listener); | |
} | |
public removeListener(event: string, listener: Listener): void { | |
if (typeof this.events[event] !== "object") { | |
return; | |
} | |
const idx: number = this.events[event].indexOf(listener); | |
if (idx > -1) { | |
this.events[event].splice(idx, 1); | |
} | |
} | |
public removeAllListeners(): void { | |
Object.keys(this.events).forEach((event: string) => | |
this.events[event].splice(0, this.events[event].length), | |
); | |
} | |
public emit(event: string, ...args: any[]): void { | |
if (typeof this.events[event] !== "object") { | |
return; | |
} | |
[...this.events[event]].forEach((listener) => listener.apply(this, args)); | |
} | |
public once(event: string, listener: Listener): () => void { | |
const remove: (() => void) = this.on(event, (...args: any[]) => { | |
remove(); | |
listener.apply(this, args); | |
}); | |
return remove; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Polyfill indexOf. */ | |
var indexOf; | |
if (typeof Array.prototype.indexOf === 'function') { | |
indexOf = function (haystack, needle) { | |
return haystack.indexOf(needle); | |
}; | |
} else { | |
indexOf = function (haystack, needle) { | |
var i = 0, length = haystack.length, idx = -1, found = false; | |
while (i < length && !found) { | |
if (haystack[i] === needle) { | |
idx = i; | |
found = true; | |
} | |
i++; | |
} | |
return idx; | |
}; | |
}; | |
/* Polyfill EventEmitter. */ | |
var EventEmitter = function () { | |
this.events = {}; | |
}; | |
EventEmitter.prototype.on = function (event, listener) { | |
if (typeof this.events[event] !== 'object') { | |
this.events[event] = []; | |
} | |
this.events[event].push(listener); | |
}; | |
EventEmitter.prototype.removeListener = function (event, listener) { | |
var idx; | |
if (typeof this.events[event] === 'object') { | |
idx = indexOf(this.events[event], listener); | |
if (idx > -1) { | |
this.events[event].splice(idx, 1); | |
} | |
} | |
}; | |
EventEmitter.prototype.emit = function (event) { | |
var i, listeners, length, args = [].slice.call(arguments, 1); | |
if (typeof this.events[event] === 'object') { | |
listeners = this.events[event].slice(); | |
length = listeners.length; | |
for (i = 0; i < length; i++) { | |
listeners[i].apply(this, args); | |
} | |
} | |
}; | |
EventEmitter.prototype.once = function (event, listener) { | |
this.on(event, function g () { | |
this.removeListener(event, g); | |
listener.apply(this, arguments); | |
}); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Listener = (...args: any[]) => void | |
type Events = { [event: string]: Listener[] }; | |
export class MyEventEmitter { | |
private readonly events: Events = {}; | |
constructor() { | |
} | |
public on(event: string, listener: Listener): () => void { | |
if(typeof this.events[event] !== 'object') this.events[event] = []; | |
this.events[event].push(listener); | |
return () => this.removeListener(event, listener); | |
} | |
public removeListener(event: string, listener: Listener): void { | |
if(typeof this.events[event] !== 'object') return; | |
const idx: number = this.events[event].indexOf(listener); | |
if(idx > -1) this.events[event].splice(idx, 1); | |
} | |
public removeAllListeners(): void { | |
Object.keys(this.events).forEach((event: string) => | |
this.events[event].splice(0, this.events[event].length) | |
); | |
} | |
public emit(event: string, ...args: any[]): void { | |
if(typeof this.events[event] !== 'object') return; | |
this.events[event].forEach(listener => listener.apply(this, args)); | |
} | |
public once(event: string, listener: Listener): void { | |
const remove: (() => void) = this.on(event, (...args: any[]) => { | |
remove(); | |
listener.apply(this, args); | |
}); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const eventify = (self) => { | |
self.events = {} | |
self.on = function (event, listener) { | |
if (typeof self.events[event] !== 'object') { | |
self.events[event] = [] | |
} | |
self.events[event].push(listener) | |
} | |
self.removeListener = function (event, listener) { | |
let idx | |
if (typeof self.events[event] === 'object') { | |
idx = self.events[event].indexOf(listener) | |
if (idx > -1) { | |
self.events[event].splice(idx, 1) | |
} | |
} | |
} | |
self.emit = function (event) { | |
var i, listeners, length, args = [].slice.call(arguments, 1); | |
if (typeof self.events[event] === 'object') { | |
listeners = self.events[event].slice() | |
length = listeners.length | |
for (i = 0; i < length; i++) { | |
listeners[i].apply(self, args) | |
} | |
} | |
} | |
self.once = function (event, listener) { | |
self.on(event, function g () { | |
self.removeListener(event, g) | |
listener.apply(self, arguments) | |
}) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let eventMixin = { | |
/** | |
* Subscribe to event, usage: | |
* menu.on('select', function(item) { ... } | |
*/ | |
on(eventName, handler) { | |
if (!this._eventHandlers) this._eventHandlers = {}; | |
if (!this._eventHandlers[eventName]) { | |
this._eventHandlers[eventName] = []; | |
} | |
this._eventHandlers[eventName].push(handler); | |
}, | |
/** | |
* Cancel the subscription, usage: | |
* menu.off('select', handler) | |
*/ | |
off(eventName, handler) { | |
let handlers = this._eventHandlers && this._eventHandlers[eventName]; | |
if (!handlers) return; | |
for (let i = 0; i < handlers.length; i++) { | |
if (handlers[i] === handler) { | |
handlers.splice(i--, 1); | |
} | |
} | |
}, | |
/** | |
* Generate the event and attach the data to it | |
* this.trigger('select', data1, data2); | |
*/ | |
trigger(eventName, ...args) { | |
if (!this._eventHandlers || !this._eventHandlers[eventName]) { | |
return; // no handlers for that event name | |
} | |
// call the handlers | |
this._eventHandlers[eventName].forEach(handler => handler.apply(this, args)); | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @flow | |
// An event handler can take an optional event argument | |
// and should not return a value | |
type EventHandler = (event?: any) => void; | |
type WildCardEventHandler = (type: string, event?: any) => void | |
// An array of all currently registered event handlers for a type | |
type EventHandlerList = Array<EventHandler>; | |
type WildCardEventHandlerList = Array<WildCardEventHandler>; | |
// A map of event types and their corresponding event handlers. | |
type EventHandlerMap = { | |
'*'?: WildCardEventHandlerList, | |
[type: string]: EventHandlerList, | |
}; | |
/** Mitt: Tiny (~200b) functional event emitter / pubsub. | |
* @name mitt | |
* @returns {Mitt} | |
*/ | |
export default function mitt(all: EventHandlerMap) { | |
all = all || Object.create(null); | |
return { | |
/** | |
* Register an event handler for the given type. | |
* | |
* @param {String} type Type of event to listen for, or `"*"` for all events | |
* @param {Function} handler Function to call in response to given event | |
* @memberOf mitt | |
*/ | |
on(type: string, handler: EventHandler) { | |
(all[type] || (all[type] = [])).push(handler); | |
}, | |
/** | |
* Remove an event handler for the given type. | |
* | |
* @param {String} type Type of event to unregister `handler` from, or `"*"` | |
* @param {Function} handler Handler function to remove | |
* @memberOf mitt | |
*/ | |
off(type: string, handler: EventHandler) { | |
if (all[type]) { | |
all[type].splice(all[type].indexOf(handler) >>> 0, 1); | |
} | |
}, | |
/** | |
* Invoke all handlers for the given type. | |
* If present, `"*"` handlers are invoked after type-matched handlers. | |
* | |
* @param {String} type The event type to invoke | |
* @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler | |
* @memberOf mitt | |
*/ | |
emit(type: string, evt: any) { | |
(all[type] || []).slice().map((handler) => { handler(evt); }); | |
(all['*'] || []).slice().map((handler) => { handler(type, evt); }); | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment