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