Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | import type {IMeta} from '@feasibleone/blong/types'; import hrtime from 'browser-process-hrtime'; type HRTime = ReturnType<typeof hrtime>; const now = (): HRTime => hrtime(); const isAfter = (time: HRTime, timeout: HRTime): boolean => Array.isArray(timeout) && (time[0] > timeout[0] || (time[0] === timeout[0] && time[1] > timeout[1])); interface IEnd { (error?: Error): void; checkTimeout: (time: HRTime) => void; } class Timeout { #calls: Set<IEnd> = new Set(); #interval: NodeJS.Timeout | undefined; protected clean(): void { Array.from(this.#calls).forEach((end: {checkTimeout: (time: HRTime) => void}) => end.checkTimeout(now()), ); } protected startWait( onTimeout: (error: Error) => void, timeout: HRTime, createTimeoutError: () => Error, set?: Set<IEnd>, ): IEnd { this.#interval = this.#interval || setInterval(this.clean.bind(this), 500); const end: IEnd = (error?: Error) => { this.endWait(end, set); if (error) onTimeout(error); }; end.checkTimeout = time => isAfter(time, timeout) && end(createTimeoutError()); this.#calls.add(end); set?.add(end); return end; } protected endWait(end: IEnd, set?: Set<IEnd>): void { this.#calls.delete(end); if (set) set.delete(end); if (this.#calls.size <= 0 && this.#interval) { clearInterval(this.#interval as NodeJS.Timeout); this.#interval = undefined; } } protected startPromise( params: unknown, fn: (params: unknown) => Promise<unknown>, $meta: IMeta, error: () => Error, set: Set<IEnd>, ): Promise<unknown> { if (Array.isArray($meta && $meta.timeout)) { return new Promise((resolve, reject) => { const endWait = this.startWait( waitError => { $meta.mtid = 'error'; if ($meta.dispatch) { Promise.resolve($meta.dispatch(waitError, $meta)).catch(() => {}); resolve(false); } else { resolve([waitError, $meta]); } }, $meta.timeout as HRTime, error, set, ); Promise.resolve(params) .then(fn) .then(result => { endWait(); resolve(result); return result; }) .catch(fnError => { endWait(); reject(fnError); }); }); } else { return Promise.resolve(params).then(fn); } } public startRequest( $meta: IMeta, error: () => Error, onTimeout: (error: Error) => void, ): IEnd | false { return ( Array.isArray($meta && $meta.timeout) && this.startWait(onTimeout, $meta.timeout as HRTime, error) ); } } export default new Timeout(); |