UNPKG

@billjs/event-emitter

Version:

A simple and lightweight EventEmitter by TypeScript for Node.js or Browsers.

262 lines (261 loc) 8.96 kB
"use strict"; /** * A simple and lightweight EventEmitter by TypeScript for Node.js or Browsers. * * @author billjs * @see https://github.com/billjs/event-emitter * @license MIT(https://opensource.org/licenses/MIT) */ Object.defineProperty(exports, "__esModule", { value: true }); /** * It's a class for managing events. * It can be extended to provide event functionality for other classes or object. * * @export * @class EventEmitter */ var EventEmitter = /** @class */ (function () { function EventEmitter() { /** * the all event handlers are added. * it's a Map data structure(key-value), the key is event type, and the value is event handler. * * @memberof EventEmitter */ this._eventHandlers = {}; } /** * event type validator. * * @param {string} type event type * @returns {boolean} * @memberof EventEmitter */ EventEmitter.prototype.isValidType = function (type) { return typeof type === 'string'; }; /** * event handler validator. * * @param {EventHandler} handler event handler * @returns {boolean} * @memberof EventEmitter */ EventEmitter.prototype.isValidHandler = function (handler) { return typeof handler === 'function'; }; /** * listen on a new event by type and handler. * if listen on, the true is returned, otherwise the false. * The handler will not be listen if it is a duplicate. * * @param {string} type event type, it must be a unique string. * @param {EventHandler} handler event handler, when if the same handler is passed, listen it by only once. * @returns {boolean} * @memberof EventEmitter * @example * const emitter = new EventEmitter(); * emitter.on('change:name', evt => { * console.log(evt); * }); */ EventEmitter.prototype.on = function (type, handler) { if (!type || !handler) return false; if (!this.isValidType(type)) return false; if (!this.isValidHandler(handler)) return false; var handlers = this._eventHandlers[type]; if (!handlers) handlers = this._eventHandlers[type] = []; // when the same handler is passed, listen it by only once. if (handlers.indexOf(handler) >= 0) return false; handler._once = false; handlers.push(handler); return true; }; /** * listen on an once event by type and handler. * when the event is fired, that will be listen off immediately and automatically. * The handler will not be listen if it is a duplicate. * * @param {string} type event type, it must be a unique string. * @param {EventHandler} handler event handler, when if the same handler is passed, listen it by only once. * @returns {boolean} * @memberof EventEmitter * @example * const emitter = new EventEmitter(); * emitter.once('change:name', evt => { * console.log(evt); * }); */ EventEmitter.prototype.once = function (type, handler) { if (!type || !handler) return false; if (!this.isValidType(type)) return false; if (!this.isValidHandler(handler)) return false; var ret = this.on(type, handler); if (ret) { // set `_once` private property after listened, // avoid to modify event handler that has been listened. handler._once = true; } return ret; }; /** * listen off an event by type and handler. * or listen off events by type, when if only type argument is passed. * or listen off all events, when if no arguments are passed. * * @param {string} [type] event type * @param {EventHandler} [handler] event handler * @returns * @memberof EventEmitter * @example * const emitter = new EventEmitter(); * // listen off the specified event * emitter.off('change:name', evt => { * console.log(evt); * }); * // listen off events by type * emitter.off('change:name'); * // listen off all events * emitter.off(); */ EventEmitter.prototype.off = function (type, handler) { // listen off all events, when if no arguments are passed. // it does samething as `offAll` method. if (!type) return this.offAll(); // listen off events by type, when if only type argument is passed. if (!handler) { this._eventHandlers[type] = []; return; } if (!this.isValidType(type)) return; if (!this.isValidHandler(handler)) return; var handlers = this._eventHandlers[type]; if (!handlers || !handlers.length) return; // otherwise, listen off the specified event. for (var i = 0; i < handlers.length; i++) { var fn = handlers[i]; if (fn === handler) { handlers.splice(i, 1); break; } } }; /** * listen off all events, that means every event will be emptied. * * @memberof EventEmitter * @example * const emitter = new EventEmitter(); * emitter.offAll(); */ EventEmitter.prototype.offAll = function () { this._eventHandlers = {}; }; /** * fire the specified event, and you can to pass a data. * When fired, every handler attached to that event will be executed. * But, if it's an once event, listen off it immediately after called handler. * * @param {string} type event type * @param {*} [data] event data * @returns * @memberof EventEmitter * @example * const emitter = new EventEmitter(); * emitter.fire('change:name', 'new name'); */ EventEmitter.prototype.fire = function (type, data) { if (!type || !this.isValidType(type)) return; var handlers = this._eventHandlers[type]; if (!handlers || !handlers.length) return; var event = this.createEvent(type, data); for (var _i = 0, handlers_1 = handlers; _i < handlers_1.length; _i++) { var handler = handlers_1[_i]; if (!this.isValidHandler(handler)) continue; if (handler._once) event.once = true; // call event handler, and pass the event argument. handler(event); // if it's an once event, listen off it immediately after called handler. if (event.once) this.off(type, handler); } }; /** * check whether the specified event has been listen on. * or check whether the events by type has been listen on, when if only `type` argument is passed. * * @param {string} type event type * @param {EventHandler} [handler] event handler, optional * @returns {boolean} * @memberof EventEmitter * @example * const emitter = new EventEmitter(); * const result = emitter.has('change:name'); */ EventEmitter.prototype.has = function (type, handler) { if (!type || !this.isValidType(type)) return false; var handlers = this._eventHandlers[type]; // if there are no any events, return false. if (!handlers || !handlers.length) return false; // at lest one event, and no pass `handler` argument, then return true. if (!handler || !this.isValidHandler(handler)) return true; // otherwise, need to traverse the handlers. return handlers.indexOf(handler) >= 0; }; /** * get the handlers for the specified event type. * * @param {string} type event type * @returns {EventHandler[]} * @memberof EventEmitter * @example * const emitter = new EventEmitter(); * const handlers = emitter.getHandlers('change:name'); * console.log(handlers); */ EventEmitter.prototype.getHandlers = function (type) { if (!type || !this.isValidType(type)) return []; return this._eventHandlers[type] || []; }; /** * create event object. * * @param {string} type event type * @param {*} [data] event data * @param {boolean} [once=false] is it an once event? * @returns {Event} * @memberof EventEmitter */ EventEmitter.prototype.createEvent = function (type, data, once) { if (once === void 0) { once = false; } var event = { type: type, data: data, timestamp: Date.now(), once: once }; return event; }; return EventEmitter; }()); exports.EventEmitter = EventEmitter; /** * EventEmitter instance for global. * @type {EventEmitter} */ exports.globalEvent = new EventEmitter();