Skip to content

Instantly share code, notes, and snippets.

@fsubal
Last active May 22, 2024 13:49
Show Gist options
  • Save fsubal/7fb4598cc7be5fb7d7766f51a10f4abd to your computer and use it in GitHub Desktop.
Save fsubal/7fb4598cc7be5fb7d7766f51a10f4abd to your computer and use it in GitHub Desktop.
export class TimeoutError extends Error {}
export class Timeout<T> {
readonly controller: AbortController
readonly error = new TimeoutError()
readonly promise: Promise<T>
constructor(
fn: (signal: AbortSignal) => Promise<T>,
timeout: number
) {
this.promise = Promise.race([
fn(this.controller.signal),
new Promise<never>((_, reject) => setTimeout(() => {
this.controller.abort(this.error)
reject(this.error)
}, timeout))
])
}
then<U>(fn: (resolved: T) => U) {
return this.promise.then(fn)
}
catch<U>(fn: (rejected: unknown) => U) {
return this.promise.catch(fn)
}
}
const timeout = await new Timeout(signal => fetch('/items', { signal }), 1000).catch(reason => {
})
export class TimeoutError extends Error {}
export function withTimeout(timeout: number) {
return function executeWithTimeout<T>(promise: Promise<T>, controller: AbortController) {
return Promise.race([
promise,
new Promise<never>((_, reject) => setTimeout(() => {
const error = new TimeoutError()
controller.abort(error)
reject(error)
}, timeout))
])
}
}
const controller = new AbortController()
const response = await withTimeout(1000)(
fetch('/items', { signal: controller.signal }), controller
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment