64 lines
1.7 KiB
TypeScript
64 lines
1.7 KiB
TypeScript
import EventEmitter from "eventemitter3";
|
|
import { withTimeout } from "@/utils";
|
|
|
|
interface HookedEvent {
|
|
date: Date;
|
|
arguments: any[];
|
|
}
|
|
|
|
const defaultCmp = () => {};
|
|
|
|
export class EventHook extends EventEmitter {
|
|
public backlog: Record<string, HookedEvent[]> = {};
|
|
|
|
public hookEmitter(emitter: EventEmitter, event: string, id: string) {
|
|
emitter.on(event, this._receivedEmitter.bind(this, id));
|
|
}
|
|
|
|
public expect(
|
|
id: string,
|
|
timeout: number = 1000,
|
|
cmp: (...args: any) => void = defaultCmp
|
|
): Promise<void> {
|
|
// Build promise
|
|
const promise = new Promise<void>((resolve, reject) => {
|
|
const getLastEvent = () => {
|
|
// Take first element in the backlog
|
|
let event = this.backlog[id].shift();
|
|
if (!event) {
|
|
// Should never happen
|
|
return reject(`undefined event in list (??)`);
|
|
}
|
|
// Send to check function, then resolve
|
|
resolve(cmp(...event.arguments));
|
|
return;
|
|
};
|
|
if (this.backlog[id] && this.backlog[id].length > 0) {
|
|
// Event is already in the backlog
|
|
getLastEvent();
|
|
} else {
|
|
// If the event hasn't fired yet, subscribe to the next time it will
|
|
this.once(id, getLastEvent);
|
|
}
|
|
});
|
|
|
|
// Return promise with added timeout
|
|
return withTimeout(promise, timeout);
|
|
}
|
|
|
|
// When events are received
|
|
private _receivedEmitter(id: string, ...args: any) {
|
|
const event: HookedEvent = {
|
|
date: new Date(),
|
|
arguments: args
|
|
};
|
|
// Create backlog if it doesn't exist
|
|
if (!this.backlog[id]) {
|
|
this.backlog[id] = [];
|
|
}
|
|
// Push to backlog and emit event (for pending expects)
|
|
this.backlog[id].push(event);
|
|
this.emit(id, event);
|
|
}
|
|
}
|