export class TimeoutTask { private interruptPromise!: Promise; private interrupt = () => {}; private totalTime = 0; constructor(private fn: () => Promise, private timeout = 0, fnName = '') { this.interruptPromise = new Promise((_, reject) => { this.interrupt = () => reject(new Error(`Timeout${fnName ? ` running ${fnName}` : ''} after ${timeout}ms.`)); }); } public async exec() { const interruptTimeout = !this.timeout ? 0 : setTimeout(this.interrupt, this.timeout); try { const start = Date.now(); const result = await Promise.race([this.fn(), this.interruptPromise]); this.totalTime = Date.now() - start; return result; } finally { clearTimeout(interruptTimeout); } } public getInterruptPromise() { return this.interruptPromise; } public getTime() { return this.totalTime; } } export const executeTimeout = async (fn: () => Promise, timeout = 0, fnName = '') => { const task = new TimeoutTask(fn, timeout, fnName); return await task.exec(); };