Skip to content

Instantly share code, notes, and snippets.

@arleighdickerson
Created November 16, 2021 23:02
Show Gist options
  • Save arleighdickerson/5393b050fcef636c298902e80582d829 to your computer and use it in GitHub Desktop.
Save arleighdickerson/5393b050fcef636c298902e80582d829 to your computer and use it in GitHub Desktop.
an emitter of typed events
export interface TypedEventListener<T> {
(event: T): void;
}
export interface TypedEventDisposable {
dispose: () => void;
}
export class TypedEvent<T> {
private readonly listeners: TypedEventListener<T>[] = [];
private oneOffs: TypedEventListener<T>[] = [];
on(listener: TypedEventListener<T>): TypedEventDisposable {
this.listeners.push(listener);
return {
dispose: () => this.off(listener),
};
}
once(listener: TypedEventListener<T>): void {
this.oneOffs.push(listener);
}
off(listener: TypedEventListener<T>): void {
this.spliceListeners(this.listeners, listener);
this.spliceListeners(this.oneOffs, listener);
}
emit(event: T): void {
this.listeners.forEach(listener => listener(event));
if (this.oneOffs.length > 0) {
const toCall = this.oneOffs;
this.oneOffs = [];
toCall.forEach(listener => listener(event));
}
}
pipe(te: TypedEvent<T>): TypedEventDisposable {
return this.on(e => te.emit(e));
}
clear() {
this.listeners.splice(0, this.listeners.length);
this.oneOffs.splice(0, this.oneOffs.length);
}
// eslint-disable-next-line class-methods-use-this
private spliceListeners(listeners: TypedEventListener<T>[], listener: TypedEventListener<T>) {
const callbackIndex = listeners.indexOf(listener);
if (callbackIndex > -1) {
listeners.splice(callbackIndex, 1);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment