events-observer
Version:
309 lines (265 loc) • 10.4 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.EventsObserver = factory());
}(this, (function () { 'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var _order = Symbol('_order');
var _processPromise = Symbol('_processPromise');
var OrderServer = function () {
function OrderServer() {
classCallCheck(this, OrderServer);
this[_order] = [];
this[_processPromise] = new Promise(function (resolve) {
return resolve();
});
}
createClass(OrderServer, [{
key: 'push',
value: function push(name, element) {
this[_order].push(name);
this[name] = element;
}
}, {
key: 'delete',
value: function _delete(name) {
var _this = this;
this[_processPromise].then(function () {
var index = _this[_order].findIndex(function (_name) {
return _name === name;
});
_this[_order].splice(index, 1);
delete _this[name];
});
}
}, {
key: 'check',
value: function check(name) {
return this.hasOwnProperty(name);
}
}, {
key: 'getItem',
value: function getItem(name) {
return this[name];
}
}, {
key: 'eachInOrder',
value: async function eachInOrder(callback) {
var resolve = function resolve() {};
this[_processPromise] = new Promise(function (_resolve) {
// open closure to resolve after async operations
resolve = _resolve;
});
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = this[_order][Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
name = _step.value;
await callback(name, this[name]);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
resolve();
}
}]);
return OrderServer;
}();
var _separator = Symbol('_separator');
var _state = Symbol('_handlersState');
var _prefix = Symbol('_prefix');
var _handlerCounter = Symbol('_handlerCounter');
var _createHandlerId = Symbol('_createHandlerId');
var _createHandlerObject = Symbol('_createHandlerObject');
var _parsePath = Symbol('_parsePath');
var _walkRecursive = Symbol('_walkRecursive');
var _callTreeRecursive = Symbol('_callTreeRecursive');
var Observer = function () {
function Observer() {
var separator = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '.';
var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '__handler_id_';
classCallCheck(this, Observer);
this[_separator] = separator;
this[_state] = new OrderServer();
this[_prefix] = prefix;
this[_handlerCounter] = 0;
}
createClass(Observer, [{
key: _createHandlerId,
value: function value() {
return this[_prefix] + this[_handlerCounter]++;
}
}, {
key: _createHandlerObject,
value: function value(handler, callLimit) {
return {
handlerId: this[_createHandlerId](),
handler: handler,
callLimit: callLimit,
callCounter: 0
};
}
}, {
key: _parsePath,
value: function value(eventPath) {
var pathArray = void 0;
if (typeof eventPath !== 'string') {
throw new Error('Event path type isn\'t correct (' + (typeof eventPath === 'undefined' ? 'undefined' : _typeof(eventPath)) + '), expected type - string');
}
pathArray = eventPath.split(this[_separator]);
if (pathArray.findIndex(function (value) {
return value === '';
}) !== -1) {
throw new Error('Event path can\'t consists of empty values');
}
return pathArray;
}
}, {
key: _walkRecursive,
value: function value(_ref) {
var path = _ref.path,
createIfEmpty = _ref.createIfEmpty,
state = _ref.state,
destinationCallback = _ref.destinationCallback,
params = _ref.params;
var isLast = path.length <= 1,
eventName = path.shift(),
// returns first element
hasEvent = state.check(eventName);
if (!hasEvent && createIfEmpty) {
state.push(eventName, new OrderServer());
hasEvent = true;
}
if (isLast) {
hasEvent && destinationCallback({ state: state, eventName: eventName, params: params });
} else {
state = state.getItem(eventName);
this[_walkRecursive]({
path: path,
createIfEmpty: createIfEmpty,
state: state,
destinationCallback: destinationCallback,
params: params
});
}
}
}, {
key: _callTreeRecursive,
value: function value(_ref2) {
var state = _ref2.state,
eventName = _ref2.eventName,
params = _ref2.params;
// to avoid context issue
var _callTreeRecursive = function _callTreeRecursive(_ref3) {
var state = _ref3.state,
eventName = _ref3.eventName,
params = _ref3.params;
return new Promise(async function (resolve) {
state = eventName && state[eventName] ? state[eventName] : state;
await state.eachInOrder(async function (name, element) {
if (element.handler) {
await element.handler(params);
++element.callCounter;
if (element.callLimit && element.callCounter >= element.callLimit) {
state.delete(name);
}
} else {
// it is event, try recursion again
await _callTreeRecursive({ state: element, params: params });
}
});
resolve();
});
};
_callTreeRecursive({ state: state, eventName: eventName, params: params });
}
}, {
key: 'on',
value: function on(event, handler) {
var callLimit = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var path = this[_parsePath](event),
handlerObject = this[_createHandlerObject](handler, callLimit);
this[_walkRecursive]({
path: path,
createIfEmpty: true,
state: this[_state],
destinationCallback: function destinationCallback(_ref4) {
var state = _ref4.state,
eventName = _ref4.eventName;
var newState = state.getItem(eventName);
newState.push(handlerObject.handlerId, handlerObject);
}
});
}
}, {
key: 'off',
value: function off(event) {
var path = this[_parsePath](event);
this[_walkRecursive]({
path: path,
state: this[_state],
destinationCallback: function destinationCallback(_ref5) {
var state = _ref5.state,
eventName = _ref5.eventName;
state.delete(eventName);
}
});
}
}, {
key: 'once',
value: function once(event, handler) {
this.on(event, handler, 1);
}
}, {
key: 'trigger',
value: function trigger(event, params) {
var path = this[_parsePath](event);
this[_walkRecursive]({
path: path,
state: this[_state],
params: params,
destinationCallback: this[_callTreeRecursive]
});
}
}]);
return Observer;
}();
return Observer;
})));