Skip to content
This repository has been archived by the owner on Oct 25, 2022. It is now read-only.

Commit

Permalink
Results are now merged + Async results
Browse files Browse the repository at this point in the history
  • Loading branch information
hazæ41 committed May 23, 2020
1 parent 90ebe8a commit e7fd7f3
Showing 1 changed file with 55 additions and 45 deletions.
100 changes: 55 additions & 45 deletions events.ts
@@ -1,61 +1,71 @@
export type Priority = "high" | "normal" | "low";
export type EventResult = "cancelled" | any[];
export type ListenerResult = "cancelled" | any[] | void;
export type Listener = (...args: any[]) => ListenerResult;
export type EventPriority = "high" | "normal" | "low";

export type EventResult = "cancelled" | any[] | void;
export type AsyncEventResult = Promise<EventResult>;

export type EventListener = (...args: any[]) => EventResult | AsyncEventResult;

export type OpenEventEmitter<T> = EventEmitter<T> | EventEmitter<any>;

export function emitter<T>(): OpenEventEmitter<T>{
return new EventEmitter<T>();
export function emitter<T>(): OpenEventEmitter<T> {
return new EventEmitter<T>();
}

function merge(a: any[], b: any[]): any[] {
const c = [...a];
for (const [i, x] of b.entries()) {
c[i] = x;
}
return c;
}

export class EventEmitter<T> {
highs = new Map<T, Set<Listener>>();
normals = new Map<T, Set<Listener>>();
lows = new Map<T, Set<Listener>>();

listeners(p: Priority): Map<T, Set<Listener>> | undefined {
if(p === "high") return this.highs;
if(p === "normal") return this.normals;
if(p === "low") return this.lows;
return undefined;
}
highs = new Map<T, Set<EventListener>>();
normals = new Map<T, Set<EventListener>>();
lows = new Map<T, Set<EventListener>>();

on([type, p = "normal"]: [T, Priority?], listener: Listener){
const listeners = this.listeners(p)
if(!listeners) return;
const set = listeners.get(type) ?? new Set();
if(!set.size) listeners.set(type, set)
set.add(listener);
}
listeners(p: EventPriority): Map<T, Set<EventListener>> | undefined {
if (p === "high") return this.highs;
if (p === "normal") return this.normals;
if (p === "low") return this.lows;
}

off([type, p = "normal"]: [T, Priority?], listener: Listener){
const listeners = this.listeners(p);
if(!listeners) return;
const set = listeners.get(type);
if(set) set.delete(listener);
}
on([type, p = "normal"]: [T, EventPriority?], listener: EventListener) {
const listeners = this.listeners(p);
if (!listeners) return;
const set = listeners.get(type) ?? new Set();
if (!set.size) listeners.set(type, set);
set.add(listener);
}

emit(type: T, ...args: any[]): EventResult {
const all = [];
off([type, p = "normal"]: [T, EventPriority?], listener: EventListener) {
const listeners = this.listeners(p);
if (!listeners) return;
const set = listeners.get(type);
if (set) set.delete(listener);
}

const highs = this.highs.get(type);
if(highs) all.push(...Array.from(highs));
async emit(type: T, ...args: any[]): Promise<"cancelled" | any[]> {
const all = [];

const normals = this.normals.get(type);
if(normals) all.push(...Array.from(normals));
const highs = this.highs.get(type);
if (highs) all.push(...Array.from(highs));

const lows = this.lows.get(type);
if(lows) all.push(...Array.from(lows));

let values = args;
const normals = this.normals.get(type);
if (normals) all.push(...Array.from(normals));

for(const listener of all){
const result = listener(...values);
if(result === "cancelled") return result;
if(Array.isArray(result)) values = result;
}
const lows = this.lows.get(type);
if (lows) all.push(...Array.from(lows));

return values;
let values = args;

for (const listener of all) {
const result = await listener(...values);
if (result === "cancelled") return result;
if (!Array.isArray(result)) continue;
values = merge(values, result);
}

return values;
}
}

0 comments on commit e7fd7f3

Please sign in to comment.