Skip to content

Instantly share code, notes, and snippets.

@shobhitsharma
Last active October 17, 2018 09:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shobhitsharma/b3501ce6b72db9447f42ffd504ee2e5a to your computer and use it in GitHub Desktop.
Save shobhitsharma/b3501ce6b72db9447f42ffd504ee2e5a to your computer and use it in GitHub Desktop.
/**
* Generic emitter of events.
*/
export interface IListenerObject {
listener: any;
remove: any;
}
export class EventSource<T> {
private listeners: Array<{
listener: (message: T) => void | boolean | Promise<boolean>;
remove?: boolean | "ifsuccessful";
}> = [];
/**
* Emit an event
*/
public emit(message: T): void {
this.listeners.slice().forEach(async (obj: IListenerObject) => {
let result;
try {
result = await obj.listener(message);
} catch (err) {
this.error_handler(err);
}
if (
obj.remove === true ||
(obj.remove === "ifsuccessful" && result === true)
) {
this.listeners.splice(this.listeners.indexOf(obj), 1);
}
});
}
/**
* If there's an error emitting an event, this is called
*/
public onError(handler: (err: Error) => void): this {
this.error_handler = handler;
return this;
}
/**
* Call a function for all events.
*/
public on(listener: (message: T) => void): this {
this.listeners.push({
listener
});
return this;
}
/**
* Call a function for the next event.
*/
public once(listener: (message: T) => void): this {
this.listeners.push({
listener,
remove: true
});
return this;
}
/**
* Call a function for all events until the function returns true.
*/
private untilTrue(
listener: (message: T) => boolean | Promise<boolean>
): this {
this.listeners.push({
listener,
remove: "ifsuccessful"
});
return this;
}
/**
* Remove all event listeners
*/
private removeAllListeners(): this {
this.listeners = [];
return this;
}
/**
* Remove a specific listener.
*/
private removeListener(listener: (message: T) => void): this {
let match = this.listeners.filter(
(obj: IListenerObject) => obj.listener === listener
);
if (match.length) {
this.listeners.splice(this.listeners.indexOf(match[0]), 1);
}
return this;
}
private error_handler: ((err: Error) => void) = (err: Error) => {
throw err;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment