Files
hermes-agent/apps/desktop/src/lib/with-timeout.ts
T
2026-08-25 22:51:31 -07:00

51 lines
1.3 KiB
TypeScript

/** Rejection raised by withTimeout. The bounded work is NOT cancelled — the
* caller decides what a straggler that settles later means. */
export class TimeoutError extends Error {
constructor(message: string) {
super(message)
this.name = 'TimeoutError'
}
}
export function isTimeoutError(error: unknown): error is TimeoutError {
return error instanceof TimeoutError
}
/** Settle with `promise`, or reject with a TimeoutError after `ms`.
* `onTimeout` runs synchronously before the rejection is published so callers
* can revoke ownership of work that would otherwise keep running unowned. If
* that callback throws, its error becomes this promise's rejection. */
export function withTimeout<T>(
promise: Promise<T>,
ms: number,
message: string,
onTimeout?: (error: TimeoutError) => void
): Promise<T> {
return new Promise<T>((resolve, reject) => {
const timer = setTimeout(() => {
const error = new TimeoutError(message)
try {
onTimeout?.(error)
} catch (onTimeoutError) {
reject(onTimeoutError)
return
}
reject(error)
}, ms)
Promise.resolve(promise).then(
value => {
clearTimeout(timer)
resolve(value)
},
err => {
clearTimeout(timer)
reject(err)
}
)
})
}