node-warp
Version:
Web-agnostic Rapid Prototyping tools
332 lines (262 loc) • 9.45 kB
JavaScript
;
var _get = require('babel-runtime/helpers/get')['default'];
var _inherits = require('babel-runtime/helpers/inherits')['default'];
var _createClass = require('babel-runtime/helpers/create-class')['default'];
var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default'];
var _slicedToArray = require('babel-runtime/helpers/sliced-to-array')['default'];
var _Map = require('babel-runtime/core-js/map')['default'];
var _Promise = require('babel-runtime/core-js/promise')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _debug = require('debug');
var _debug2 = _interopRequireDefault(_debug);
var _events = require('events');
var _events2 = _interopRequireDefault(_events);
var _co = require('co');
var _co2 = _interopRequireDefault(_co);
var _utils = require('./utils');
var Bus = (function (_EventEmitter) {
_inherits(Bus, _EventEmitter);
_createClass(Bus, null, [{
key: 'formatReplyEvent',
value: function formatReplyEvent(correlationId) {
return 'reply::' + correlationId;
}
}]);
function Bus() {
_classCallCheck(this, Bus);
_get(Object.getPrototypeOf(Bus.prototype), 'constructor', this).call(this);
this.debug = (0, _debug2['default'])('bus');
this._managedHandlers = new _Map();
}
/**
* @desc Emits an event (asynchronously)
* @param {String} event
* @param {*} [args]
* @return {Promise}
*/
_createClass(Bus, [{
key: 'emit',
value: function emit(event) {
var _this = this;
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
return new _Promise(function (resolve) {
return process.nextTick(function () {
var _get3;
if (event !== 'event') {
var _get2;
(_get2 = _get(Object.getPrototypeOf(Bus.prototype), 'emit', _this)).call.apply(_get2, [_this, 'event', event].concat(args));
}
resolve((_get3 = _get(Object.getPrototypeOf(Bus.prototype), 'emit', _this)).call.apply(_get3, [_this, event].concat(args)));
});
});
}
/**
* @desc Subscribes to event with given callback
* @param {String} event
* @param {function|GeneratorFunction} callback
* @param {Object} [context]
* @return {EventEmitter}
*/
}, {
key: 'on',
value: function on(event, callback, context) {
var _callback = _co2['default'].wrap(callback);
if (context) {
_callback = _callback.bind(context);
}
var handler = function handler() {
return _callback.apply(undefined, arguments);
};
this._pushManagedHandler(event, callback, handler);
return _get(Object.getPrototypeOf(Bus.prototype), 'on', this).call(this, event, handler);
}
/**
* @desc Subscribes to event with given callback, and unsubscribes once it fired
* @param {String} event
* @param {function|GeneratorFunction} callback
* @param {Object} [context]
* @return {EventEmitter}
*/
}, {
key: 'once',
value: function once(event, callback, context) {
var _this2 = this;
var _callback = _co2['default'].wrap(callback);
if (context) {
_callback = _callback.bind(context);
}
var handler = function handler() {
_this2.off(event, callback);
return _callback.apply(undefined, arguments)['catch'](function (err) {
throw new Error(err);
});
};
this._pushManagedHandler(event, callback, handler);
return _get(Object.getPrototypeOf(Bus.prototype), 'on', this).call(this, event, handler);
}
}, {
key: 'onRequest',
value: function onRequest(event, callback, context) {
var _this3 = this;
var handler = function handler(requestData, header) {
var _callback = _co2['default'].wrap(callback);
if (context) {
_callback = _callback.bind(context);
}
return _callback(requestData, header)['catch'](function (err) {
header.error = true;
return err;
}).then(function (replyData) {
var replyEvent = Bus.formatReplyEvent(header.correlationId);
header.replied = Date.now();
return _this3.emit(replyEvent, replyData, header);
});
};
this._pushManagedHandler(event, callback, handler);
_get(Object.getPrototypeOf(Bus.prototype), 'on', this).call(this, event, handler);
}
/**
* @desc Unsubscribes of event with given callback
* @param {String} event
* @param {function} callback
* @return {Number}
*/
}, {
key: 'off',
value: function off(event, callback) {
var managedCallback = this._popManagedHandler(event, callback);
return _get(Object.getPrototypeOf(Bus.prototype), 'removeListener', this).call(this, event, managedCallback);
}
}, {
key: 'removeListener',
value: function removeListener(event, callback) {
return this.off(event, callback);
}
}, {
key: 'removeAllListeners',
value: function removeAllListeners() {
this._resetManagedHandlers();
return _get(Object.getPrototypeOf(Bus.prototype), 'removeAllListeners', this).call(this);
}
/**
* @desc Returns promise, resolved later by event with message given, or rejected by timeout.
* @param {String} event
* @param {Number} [timeout = 0]
* @return {Promise}
*/
}, {
key: 'wait',
value: function wait(event) {
var _this4 = this;
var timeout = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
var _timeout = parseInt(timeout, 10);
return new _Promise(function (resolve, reject) {
var _timer = null;
function _handleFn() {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
if (_timer > 0) {
clearTimeout(_timer);
}
if (args.length < 2) {
var _args = args;
var _args2 = _slicedToArray(_args, 1);
args = _args2[0];
}
return resolve(args);
}
if (_timeout > 0) {
_timer = setTimeout(function () {
_this4.off(event, _handleFn);
reject('timed out');
}, _timeout);
}
_this4.once(event, _handleFn);
});
}
/**
* Returns promise resolved by replyFn (wrapped within request handler last argument) on subscriber's side,
* or rejected by timeout
* @param {String|Number} event
* @param {*} [data]
* @param {Number} [timeout = 0]
* @param {String} [from = 'global']
* @return {Promise}
*/
}, {
key: 'request',
value: function request(event, data) {
var timeout = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
var from = arguments.length <= 3 || arguments[3] === undefined ? 'global' : arguments[3];
var _correlationId = _utils.random.string(8, 4);
var _replyEvent = Bus.formatReplyEvent(_correlationId);
var _header = {
correlationId: _correlationId,
from: from,
created: Date.now()
};
this.emit(event, data, _header);
this.debug('request: ' + event + ' (' + _correlationId + ')');
if (timeout) {
this.debug('request: timeout => ' + timeout + ' ms');
}
return this.wait(_replyEvent, timeout).then(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2);
var replyData = _ref2[0];
var replyHeader = _ref2[1];
if (!replyHeader) {
throw new Error('reply header missing');
}
if (replyHeader.error) {
throw replyData;
}
return replyData;
});
}
}, {
key: '_pushManagedHandler',
value: function _pushManagedHandler(event, originalHandler, managedHandler) {
var handlerList = this._managedHandlers.get(event);
this.debug('managed handlers: adding ' + event + ' => ' + originalHandler.name);
if (!handlerList) {
handlerList = new _Map();
this._managedHandlers.set(event, handlerList);
}
handlerList.set(originalHandler, managedHandler);
}
}, {
key: '_popManagedHandler',
value: function _popManagedHandler(event, originalHandler) {
var handlerList = this._managedHandlers.get(event);
if (!handlerList) {
return originalHandler;
}
var managedHandler = handlerList.get(originalHandler);
if (!managedHandler) {
return originalHandler;
}
this.debug('managed handlers: checking ' + event + ' => ' + originalHandler.name);
handlerList['delete'](originalHandler);
if (handlerList.size === 0) {
this._managedHandlers['delete'](event);
}
this.debug('managed handlers: found and deleted');
return managedHandler;
}
}, {
key: '_resetManagedHandlers',
value: function _resetManagedHandlers() {
this._managedHandlers = new _Map();
}
}]);
return Bus;
})(_events2['default']);
exports['default'] = Bus;
module.exports = exports['default'];
//# sourceMappingURL=bus.js.map