squee
Version:
Super quick event emitter!
191 lines • 9.23 kB
JavaScript
System.register("index", [], function (exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
var removeFromArray, createNewRegistration, EventEmitter, Squee;
return {
setters: [],
execute: function () {
/**
* Removes any instances of an item from an array.
*
* @template TItem Types of items in the array.
* @param array Array of items.
* @param item Item to remove.
* @returns Whether any number of that item was removed.
*/
removeFromArray = function (array, item) {
var removed = false;
for (var i = 0; i < array.length; i += 1) {
if (array[i] === item) {
removed = true;
array.splice(i, 1);
i -= 1;
}
}
return removed;
};
/**
* Creates a new, blank registration.
*
* @returns A new, blank registration.
*/
createNewRegistration = function () { return ({
firstOnlyListeners: [],
listeners: []
}); };
/**
* Hub for triggerable application events.
*
* @template TTypes Event names linked to their arg types.
*/
EventEmitter = /** @class */ (function () {
function EventEmitter() {
/**
* Listeners to fire on all events.
*/
this.anyRegistrations = [];
/**
* Listeners and first args registered to events.
*/
this.registrations = {};
}
/**
* Binds an event listener to an event name.
*
* @param eventName Name of an event.
* @param listener Listener for the event.
*/
EventEmitter.prototype.on = function (eventName, listener) {
this.safelyGetRegistration(eventName)
.listeners.push(listener);
};
/**
* Binds an event listener to the first time an event name.
*
* @param eventName Name of an event.
* @param listener Listener for the event.
* @remarks If the event name was already fired, it's immediately called with the args from the first event.
*/
EventEmitter.prototype.onFirst = function (eventName, listener) {
var registration = this.safelyGetRegistration(eventName);
if (registration.firstArgs !== undefined) {
listener.apply(void 0, registration.firstArgs);
}
registration.firstOnlyListeners.push(listener);
};
/**
* Binds an event listener to all events.
*
* @param listener Called on any event with the event name and args.
*/
EventEmitter.prototype.onAny = function (listener) {
this.anyRegistrations.push(listener);
};
/**
* Removes an event listener from an event name.
* If no listener is provided, it removes all listeners for that event name.
* If no event name is provided, it removes all listeners for all event names.
*
* @param eventName Name of an event, if not all events.
* @param listener Listener for the event, if not all listeners for the event(s).
* @remarks Throws an error if the listener wasn't added for that event name.
*/
EventEmitter.prototype.off = function (eventName, listener) {
if (eventName === undefined) {
this.registrations = {};
return;
}
if (listener === undefined) {
this.registrations[eventName] = createNewRegistration();
return;
}
var registration = this.safelyGetRegistration(eventName);
var wasInListeners = removeFromArray(registration.listeners, listener);
var wasInFirstOnlyListeners = removeFromArray(registration.firstOnlyListeners, listener);
if (!wasInListeners && !wasInFirstOnlyListeners) {
throw new Error("Tried to remove a non-existent listener for event name '" + eventName + "'.");
}
};
/**
* Emits an event, along with any amount of additional information.
*
* @param eventName Name of an event.
* @param args Any additional information for the event.
*/
EventEmitter.prototype.emit = function (eventName) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var registration = this.safelyGetRegistration(eventName);
if (registration.firstArgs === undefined) {
for (var _a = 0, _b = registration.firstOnlyListeners; _a < _b.length; _a++) {
var firstOnlyListener = _b[_a];
firstOnlyListener.apply(void 0, args);
}
registration.firstArgs = args;
registration.firstOnlyListeners = [];
}
for (var _c = 0, _d = registration.listeners; _c < _d.length; _c++) {
var listener = _d[_c];
listener.apply(void 0, args);
}
for (var _e = 0, _f = this.anyRegistrations; _e < _f.length; _e++) {
var listener = _f[_e];
listener.apply(void 0, [eventName].concat(args));
}
};
/**
* Creates a Promise to be resolved the next time an event is fired.
*
* @param eventName Name of an event.
* @returns A Promise to be resolved with the first object passed with the event.
*/
EventEmitter.prototype.waitFor = function (eventName) {
var _this = this;
return new Promise(function (resolve) {
var listener = function (arg) {
resolve(arg);
_this.off(eventName, listener);
};
_this.on(eventName, listener);
});
};
/**
* Creates a Promise to be resolved the first time an event is fired.
*
* @param eventName Name of an event.
* @returns A Promise to be resolve with the first object passed with the first event.
* @remarks If the event name was already fired, it's immediately resolved with the args from the first event.
*/
EventEmitter.prototype.waitForFirst = function (eventName) {
var _this = this;
return new Promise(function (resolve) {
var listener = function (arg) {
resolve(arg);
_this.off(eventName, listener);
};
_this.onFirst(eventName, listener);
});
};
/**
* Ensures the registrations object for an event exists.
*
* @param eventName Name of an event.
* @returns Registrations for the event.
*/
EventEmitter.prototype.safelyGetRegistration = function (eventName) {
if (this.registrations[eventName] === undefined) {
this.registrations[eventName] = createNewRegistration();
}
// See https://github.com/Microsoft/TypeScript/issues/10530
return this.registrations[eventName];
};
return EventEmitter;
}());
exports_1("EventEmitter", EventEmitter);
exports_1("Squee", Squee = EventEmitter);
}
};
});
//# sourceMappingURL=squee-system-es3.js.map