Base and Emitter classes
This commit is contained in:
commit
7a2b1d3e5f
38
base.js
Normal file
38
base.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
mimicry.module(function baseModule () {
|
||||||
|
let counter = 0;
|
||||||
|
class Base {
|
||||||
|
constructor () {
|
||||||
|
this._id = ++counter;
|
||||||
|
this._uncyclic = [];
|
||||||
|
}
|
||||||
|
get className () {
|
||||||
|
return this.constructor.name;
|
||||||
|
}
|
||||||
|
get id () {
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
destructor () {
|
||||||
|
for (let i = 0; i < this._uncyclic.length; ++i) {
|
||||||
|
try {
|
||||||
|
this._uncyclic[i].call(this);
|
||||||
|
} catch (e) {
|
||||||
|
//log probably
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let key in this) {
|
||||||
|
if (this.hasOwnProperty(key)) {
|
||||||
|
this[key] = undefined;
|
||||||
|
delete this[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.destroyed = true;
|
||||||
|
}
|
||||||
|
recycle (/*Function*/fn) {
|
||||||
|
this._uncyclic.push(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Base;
|
||||||
|
});
|
151
emitter.js
Normal file
151
emitter.js
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
mimicry.module([
|
||||||
|
"./base"
|
||||||
|
], function emitterModule(global, [Base]) {
|
||||||
|
class Emitter extends Base {
|
||||||
|
constructor () {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._events = Object.create(null);
|
||||||
|
this._accumulatedEvents = Object.create(null);
|
||||||
|
}
|
||||||
|
destructor () {
|
||||||
|
this.off();
|
||||||
|
|
||||||
|
super.destructor();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Subscribes to event
|
||||||
|
*
|
||||||
|
* @param {String} name - name of the event you want to subscribe
|
||||||
|
* @param {Function} handler - a handler you want to perform on the event
|
||||||
|
* @param {Object} [context] - a context you want to perform your handler with
|
||||||
|
* */
|
||||||
|
on (name, handler, context) {
|
||||||
|
let handlers = this._events[name];
|
||||||
|
|
||||||
|
if (typeof name !== "string")
|
||||||
|
throw new Error("Name of event is mandatory");
|
||||||
|
|
||||||
|
if (!(handler instanceof Function))
|
||||||
|
throw new Error("Handler of event is mandatory");
|
||||||
|
|
||||||
|
if (!handlers) {
|
||||||
|
handlers = [];
|
||||||
|
this._events[name] = handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
handlers.push({
|
||||||
|
handler: handler,
|
||||||
|
context: context || this,
|
||||||
|
once: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Subscribes to event, but the handler is called only once
|
||||||
|
*
|
||||||
|
* @param {String} name - name of the event you want to subscribe
|
||||||
|
* @param {Function} handler - a handler you want to perform on the event
|
||||||
|
* @param {Object} [context] - a context you want to perform your handler with
|
||||||
|
* */
|
||||||
|
one (name, handler, context) {
|
||||||
|
this.on(name, handler, context);
|
||||||
|
this._events[name][this._events[name].length - 1].once = true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Unsubscribes from event
|
||||||
|
*
|
||||||
|
* @param {String} [name] - name of the event you want to unsubscribe from.
|
||||||
|
* If not passed unsubscribes every subscribed handler from all events
|
||||||
|
* @param {Function} [handler] - a handler you want to unsubscribe.
|
||||||
|
* If not passed unsubscribes all handlers from event defined by "name" parameter
|
||||||
|
* @param {Object} [context] - a context you want to unsubscribe.
|
||||||
|
* If not passed unsubscribes all matching handlers from
|
||||||
|
* event defined by "name" parameter.
|
||||||
|
* */
|
||||||
|
off (name, handler, context) {
|
||||||
|
if (typeof name !== "string") {
|
||||||
|
this._events = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._events[name])
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(handler instanceof Function)) {
|
||||||
|
delete this._events[name];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlers = this._events[name];
|
||||||
|
for (let i = handlers.length - 1; i >= 0; --i) {
|
||||||
|
if (handlers[i].handler === handler) {
|
||||||
|
if (context || context === null) {
|
||||||
|
if (handlers[i].context === context)
|
||||||
|
handlers.splice(i, 1);
|
||||||
|
} else {
|
||||||
|
handlers.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Emits event name with given parameters
|
||||||
|
*
|
||||||
|
* @param {String} name - name of the emitting event
|
||||||
|
* @param {...Array} [params] - list of parameters separated by comma
|
||||||
|
* */
|
||||||
|
emit (...[name, ...params]) {
|
||||||
|
if (this._accumulatedEvents[name]) {
|
||||||
|
this._accumulatedEvents[name] = params;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const handlers = this._events[name];
|
||||||
|
if (!handlers)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (let i = 0; i < handlers.length; ++i) {
|
||||||
|
const handle = handlers[i];
|
||||||
|
handle.handler.apply(handle.context, params);
|
||||||
|
if (handle.once)
|
||||||
|
handlers.splice(i--, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Counts how many handlers are subscribed to given event name
|
||||||
|
*
|
||||||
|
* @param {String} name - name of the event
|
||||||
|
*
|
||||||
|
* @returns {Number} - how many handlers are subscribed to given event
|
||||||
|
* */
|
||||||
|
countHandlers (name) {
|
||||||
|
return this._events[name] && this._events[name].length || 0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* You can call this method and emit(name) will stop notifying subscribers
|
||||||
|
* It will keep the last event parameters event was called with instead
|
||||||
|
* This way you can avoid multiple notifications of the same event
|
||||||
|
*
|
||||||
|
* @param {String} name - event name
|
||||||
|
* */
|
||||||
|
accumulateEvent (name) {
|
||||||
|
this._accumulatedEvents[name] = true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This method stops accumulation of the event and emits it
|
||||||
|
* if there were emissions during accumulation period
|
||||||
|
* If there were several emissions - event is emitted with the last set of parameters
|
||||||
|
*
|
||||||
|
* @param {String} name - event name
|
||||||
|
* */
|
||||||
|
releaseEvent (name) {
|
||||||
|
const params = this._accumulatedEvents[name];
|
||||||
|
delete this._accumulatedEvents[name];
|
||||||
|
if (params instanceof Array) {
|
||||||
|
params.unshift(name);
|
||||||
|
this.emit.apply(this, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Emitter;
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user