UNPKG

diffusion

Version:

Diffusion JavaScript client

292 lines (291 loc) 9.56 kB
"use strict"; /** * @module events */ var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Emitter = void 0; var errors_1 = require("./../../errors/errors"); var stream_1 = require("./../events/stream"); var functions = require("./../util/function"); var EmitterEventQueue = /** @class */ (function () { function EmitterEventQueue() { this.pendingEvents = []; this.events = []; this.busy = false; } /** * Add an emitter event to the queue */ EmitterEventQueue.prototype.addEmitterEvent = function (event) { var _this = this; this.pendingEvents.push(event); if (!this.busy) { this.busy = true; process.nextTick(function () { _this.drainEmitterQueue(); }); } }; /** * Process all pending events */ EmitterEventQueue.prototype.drainEmitterQueue = function () { var e_1, _a; var _this = this; this.events = this.pendingEvents; this.pendingEvents = []; try { for (var _b = __values(this.events), _c = _b.next(); !_c.done; _c = _b.next()) { var event_1 = _c.value; try { event_1(); } catch (err) { /* no-op */ } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } if (this.pendingEvents.length > 0) { process.nextTick(function () { _this.drainEmitterQueue(); }); } else { this.busy = false; } }; return EmitterEventQueue; }()); var emitterEventQueue = new EmitterEventQueue(); /** * An internal class to construct implementations of {@link events.Stream} with * a privately scoped emit function. * * This allows safe construction of event-based interfaces without exposing the * means of emitting events. */ var Emitter = /** @class */ (function () { /** * Create an Emitter * * If a {@link Stream} is provided in the options, the Emitter will use it as * the stream to emit events to. In this case, the `listeners` must also be * supplied. * * If no {@link Stream} is provided, one will be created with the optional * `allowedEvents` option. * * If the `event` option is specified, listeners will be registered by calling * {@link Stream.on} passing the `event` option and the `callback` option as * parameters. * * @param options options for creating the Emitter */ function Emitter(options) { var _this = this; /** * The listeners object mapping event names to arrays of callback functions */ this.listeners = {}; /** * A flag indicating whether the Emitter is closed */ this.closed = false; /** * A single listener that will be called whenever an event is emitted. The * event name will be passed as the first argument. */ this.listener = function () { }; if (options === undefined || options.stream === undefined) { var helper = { getListeners: function () { return _this.listeners; }, getErrorCallback: function () { return _this.error.bind(_this); }, getCloseCallback: function () { return _this.close.bind(_this); } }; this.stream = new stream_1.StreamImpl(helper); } else { this.stream = options.stream; if (options.listeners === undefined) { throw new errors_1.InternalError('Listeners must be defined when supplying a stream'); } this.listeners = options.listeners; } if (options !== undefined && options.event !== undefined) { this.stream.on(options.event, options.callback); } } /** * Create an emitter factory that can create an Emitter. * * @param allowedEvents a list of allowed event names * @return a factory that creates an Emitter */ Emitter.create = function () { var listeners = {}; var errorCallback = function () { }; var closeCallback = function () { }; return { getListeners: function () { return listeners; }, getErrorCallback: function () { return function (err) { errorCallback(err); }; }, getCloseCallback: function () { return function (reason) { closeCallback(reason); }; }, emitter: function (stream) { var emitter = new Emitter({ stream: stream, listeners: listeners }); errorCallback = emitter.error.bind(emitter); closeCallback = emitter.close.bind(emitter); return emitter; } }; }; /** * Emit an event without checking if the emitter is closed. * * @see {@link Emitter.emit} * * @param event the event name * @param args arguments to pass to the listeners */ Emitter.prototype.emitUnsafe = function (event, args) { var _this = this; var dispatch = function (listener) { functions.callWithArguments(listener, args || []); }; emitterEventQueue.addEmitterEvent(function () { // eslint-disable-next-line no-prototype-builtins if (_this.listeners.hasOwnProperty(event)) { _this.listeners[event].forEach(dispatch); } }); this.listener(event, args); }; /** * Emit an event. * * When an event is emitted, all listeners registered with the `Stream` for * this event will be called. * * If the emitter is closed, or no `event` is specified, nothing will be emitted. * * Any additional arguments will be passed to the listeners. * * @param event the event name * @param args arguments to pass to the listeners */ Emitter.prototype.emit = function (event) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } if (this.closed || !event) { return; } this.emitUnsafe(event, args); }; /** * Process an event immediately. * * <p>Experimental. */ Emitter.prototype.immediate = function (event) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } if (this.closed || !event) { return; } var dispatch = function (listener) { try { functions.callWithArguments(listener, args || []); } catch (err) { /* no-op */ } }; // eslint-disable-next-line no-prototype-builtins if (this.listeners.hasOwnProperty(event)) { this.listeners[event].forEach(dispatch); } }; /** * Signal a error and close the emitter. This will emit an `error` event and * subsequently a `close` event. No further events will be emitted. * * @param reason the error causing the emitter to close */ Emitter.prototype.error = function (reason) { if (this.closed) { return; } this.emitUnsafe('error', [reason]); this.close((reason) ? reason.message : undefined); }; /** * Close the emitter. This will emit a `close` event. * No further events will be emitted. * * @param reason the reason for closing the emitter. This can be of any type. * The type of the close reason should be documented in the * concrete implementation of the {@link Stream} that the * emitter is linked to. */ Emitter.prototype.close = function (reason) { if (this.closed) { return; } this.closed = true; this.emitUnsafe('close', [reason]); }; /** * Add a listener to all events * * @param fn a callback function that will be called whenever an event is * emitted. The event name will be passed as the first argument. */ Emitter.prototype.listen = function (fn) { this.listener = fn; }; /** * Get the stream that is used to register the callbacks * * @return the internal stream object */ Emitter.prototype.get = function () { return this.stream; }; return Emitter; }()); exports.Emitter = Emitter;