UNPKG

@nathanfaucett/event_emitter

Version:

EventEmitter for the browser and node.js

427 lines (346 loc) 10.2 kB
var isFunction = require("@nathanfaucett/is_function"), inherits = require("@nathanfaucett/inherits"), apply = require("@nathanfaucett/apply"), fastSlice = require("@nathanfaucett/fast_slice"), keys = require("@nathanfaucett/keys"), isNumber = require("@nathanfaucett/is_number"), isNullOrUndefined = require("@nathanfaucett/is_null_or_undefined"); var EventEmitterPrototype; module.exports = EventEmitter; function EventEmitter(maxListeners) { this._events = {}; this._maxListeners = isNumber(maxListeners) ? +maxListeners : EventEmitter.defaultMaxListeners; } EventEmitterPrototype = EventEmitter.prototype; EventEmitterPrototype.on = function(name, listener) { var events, eventList, maxListeners; if (!isFunction(listener)) { throw new TypeError( "EventEmitter.on(name, listener) listener must be a function" ); } events = this._events || (this._events = {}); eventList = events[name] || (events[name] = []); maxListeners = this._maxListeners || -1; eventList.push(listener); if (maxListeners !== -1 && eventList.length > maxListeners) { console.error( "EventEmitter.on(type, listener) possible EventEmitter memory leak detected. " + maxListeners + " listeners added" ); } return this; }; EventEmitterPrototype.addEventListener = EventEmitterPrototype.addListener = EventEmitterPrototype.on; EventEmitterPrototype.once = function(name, listener) { var _this = this; function once() { var result = apply(listener, arguments, _this); _this.off(name, once); return result; } this.on(name, once); return once; }; EventEmitterPrototype.listenTo = function(value, name) { var _this = this; if (!value || !(isFunction(value.on) || isFunction(value.addListener))) { throw new TypeError( "EventEmitter.listenTo(value, name) value must have a on function taking (name, listener[, ctx])" ); } function handler() { _this.emitArgs(name, arguments); } value.on(name, handler); return handler; }; EventEmitterPrototype.off = function(name, listener) { var events = this._events || (this._events = {}), eventList = events[name], event, i; if (!eventList) { return this; } else { if (!listener) { i = eventList.length; while (i--) { this.emit("removeListener", name, eventList[i]); } delete events[name]; } else { i = eventList.length; while (i--) { event = eventList[i]; if (event === listener) { this.emit("removeListener", name, event); eventList.splice(i, 1); } } if (eventList.length === 0) { delete events[name]; } } return this; } }; EventEmitterPrototype.removeEventListener = EventEmitterPrototype.removeListener = EventEmitterPrototype.off; EventEmitterPrototype.removeAllListeners = function() { var events = this._events || (this._events = {}), objectKeys = keys(events), i = objectKeys.length, key, eventList, j; while (i--) { key = objectKeys[i]; eventList = events[key]; if (eventList) { j = eventList.length; while (j--) { this.emit("removeListener", key, eventList[j]); } delete events[key]; } } return this; }; EventEmitterPrototype.dispatchEvent = function(event) { return this.emitArg(event.type, event); }; EventEmitterPrototype.attachEvent = function(type, listener) { return this.on(type.slice(2), listener); }; EventEmitterPrototype.detachEvent = function(type, listener) { return this.off(type.slice(2), listener); }; EventEmitterPrototype.fireEvent = function(type, event) { return this.emitArg(type.slice(2), event); }; function emit0(_this, eventList) { var i = -1, il = eventList.length - 1, event; while (i++ < il) { if ((event = eventList[i])) { event.call(_this); } } } function emit1(_this, eventList, a0) { var i = -1, il = eventList.length - 1, event; while (i++ < il) { if ((event = eventList[i])) { event.call(_this, a0); } } } function emit2(_this, eventList, args) { var a0 = args[0], a1 = args[1], i = -1, il = eventList.length - 1, event; while (i++ < il) { if ((event = eventList[i])) { event.call(_this, a0, a1); } } } function emit3(_this, eventList, args) { var a0 = args[0], a1 = args[1], a2 = args[2], i = -1, il = eventList.length - 1, event; while (i++ < il) { if ((event = eventList[i])) { event.call(_this, a0, a1, a2); } } } function emit4(_this, eventList, args) { var a0 = args[0], a1 = args[1], a2 = args[2], a3 = args[3], i = -1, il = eventList.length - 1, event; while (i++ < il) { if ((event = eventList[i])) { event.call(_this, a0, a1, a2, a3); } } } function emit5(_this, eventList, args) { var a0 = args[0], a1 = args[1], a2 = args[2], a3 = args[3], a4 = args[4], i = -1, il = eventList.length - 1, event; while (i++ < il) { if ((event = eventList[i])) { event.call(_this, a0, a1, a2, a3, a4); } } } function emitApply(_this, eventList, args) { var i = -1, il = eventList.length - 1, event; while (i++ < il) { if ((event = eventList[i])) { event.apply(_this, args); } } } function emit(_this, eventList, args) { switch (args.length) { case 0: emit0(_this, eventList); break; case 1: emit1(_this, eventList, args[0]); break; case 2: emit2(_this, eventList, args); break; case 3: emit3(_this, eventList, args); break; case 4: emit4(_this, eventList, args); break; case 5: emit5(_this, eventList, args); break; default: emitApply(_this, eventList, args); break; } } EventEmitterPrototype.emitArg = function(name, arg) { var eventList = (this._events || (this._events = {}))[name]; if (!eventList || !eventList.length) { return this; } else { emit1(this, eventList, arg); return this; } }; EventEmitterPrototype.emitArgs = function(name, args) { var eventList = (this._events || (this._events = {}))[name]; if (!eventList || !eventList.length) { return this; } else { emit(this, eventList, args); return this; } }; EventEmitterPrototype.emit = function(name) { return this.emitArgs(name, fastSlice(arguments, 1)); }; function emitAsync(_this, eventList, args, callback) { var length = eventList.length, index = 0, called = false; function next(error) { if (called !== true) { if (error || index === length) { called = true; callback(error); } else { apply(eventList[index++], args, _this); } } } args.push(next); next(); } EventEmitterPrototype.emitAsync = function(name) { var eventList = (this._events || (this._events = {}))[name], args = fastSlice(arguments, 1), callback = args.pop(); if (!isFunction(callback)) { throw new TypeError( "EventEmitter.emitAsync(name [, ...args], callback) callback must be a function" ); } else { if (!eventList || !eventList.length) { callback(); } else { emitAsync(this, eventList, args, callback); } return this; } }; EventEmitterPrototype.listeners = function(name) { var eventList = (this._events || (this._events = {}))[name]; return eventList ? eventList.slice() : []; }; EventEmitterPrototype.listenerCount = function(name) { var events = this._events, eventList; if (events) { eventList = events[name]; return eventList ? eventList.length : 0; } else { return 0; } }; EventEmitterPrototype.setMaxListeners = function(value) { if ((value = +value) !== value) { throw new TypeError( "EventEmitter.setMaxListeners(value) value must be a number" ); } this._maxListeners = value < 0 ? -1 : value; return this; }; inherits.defineProperty(EventEmitter, "defaultMaxListeners", 10); inherits.defineProperty(EventEmitter, "listeners", function(value, name) { var eventList; if (isNullOrUndefined(value)) { throw new TypeError( "EventEmitter.listeners(value, name) value required" ); } eventList = value._events && value._events[name]; return eventList ? eventList.slice() : []; }); inherits.defineProperty(EventEmitter, "listenerCount", function(value, name) { var eventList; if (isNullOrUndefined(value)) { throw new TypeError( "EventEmitter.listenerCount(value, name) value required" ); } eventList = value._events && value._events[name]; return eventList ? eventList.length : 0; }); inherits.defineProperty(EventEmitter, "setMaxListeners", function(value) { if ((value = +value) !== value) { throw new TypeError( "EventEmitter.setMaxListeners(value) value must be a number" ); } EventEmitter.defaultMaxListeners = value < 0 ? -1 : value; return value; }); EventEmitter.extend = function(child) { inherits(child, this); return child; };