This repository has been archived by the owner on Oct 25, 2022. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Results are now merged + Async results
- Loading branch information
hazæ41
committed
May 23, 2020
1 parent
90ebe8a
commit e7fd7f3
Showing
1 changed file
with
55 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |