UNPKG

zigbee-herdsman-zigate

Version:

An open source ZigBee gateway solution with node.js.

81 lines (69 loc) 2.73 kB
interface Waiter<TPayload, TMatcher> { ID: number; resolve: (payload: TPayload) => void; reject: (error: Error) => void; // eslint-disable-next-line timer?: any; resolved: boolean; timedout: boolean; matcher: TMatcher; } type Validator<TPayload, TMatcher> = (payload: TPayload, matcher: TMatcher) => boolean; type TimeoutFormatter<TMatcher> = (matcher: TMatcher, timeout: number) => string; class Waitress<TPayload, TMatcher> { private waiters: Map<number, Waiter<TPayload, TMatcher>>; private validator: Validator<TPayload, TMatcher>; private timeoutFormatter: TimeoutFormatter<TMatcher>; private currentID: number; public constructor(validator: Validator<TPayload, TMatcher>, timeoutFormatter: TimeoutFormatter<TMatcher>) { this.waiters = new Map(); this.timeoutFormatter = timeoutFormatter; this.validator = validator; this.currentID = 0; } public resolve(payload: TPayload): void { for (const entry of this.waiters.entries()) { const index = entry[0]; const waiter = entry[1]; if (waiter.timedout) { this.waiters.delete(index); } else if (this.validator(payload, waiter.matcher)) { clearTimeout(waiter.timer); waiter.resolved = true; waiter.resolve(payload); this.waiters.delete(index); } } } public remove(ID: number): void { const waiter = this.waiters.get(ID); if (waiter) { if (!waiter.timedout && waiter.timer) { clearTimeout(waiter.timer); } this.waiters.delete(ID); } } public waitFor( matcher: TMatcher, timeout: number ): {ID: number; start: () => {promise: Promise<TPayload>; ID: number}} { const ID = this.currentID++; const promise: Promise<TPayload> = new Promise((resolve, reject): void => { const object: Waiter<TPayload, TMatcher> = {matcher, resolve, reject, timedout: false, resolved: false, ID}; this.waiters.set(ID, object); }); const start = (): {promise: Promise<TPayload>; ID: number} => { const waiter = this.waiters.get(ID); if (waiter && !waiter.resolved && !waiter.timer) { waiter.timer = setTimeout((): void => { const message = this.timeoutFormatter(matcher, timeout); waiter.timedout = true; waiter.reject(new Error(message)); }, timeout); } return {promise, ID}; }; return {ID, start}; } } export default Waitress;