Use AbortSignal.timeout + custom timeout error message (#1718)

* refactor: replace custom logic with AbortSignal.timeout

* Use custom timeout error message

* Include method and url in fetch timeout error

* Fix error not rethrown
This commit is contained in:
ekzyis 2024-12-13 15:38:42 +01:00 committed by GitHub
parent e8434d07c5
commit fc4303658d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 10 deletions

View File

@ -1,14 +1,26 @@
import { TimeoutError } from '@/lib/time'
class FetchTimeoutError extends TimeoutError {
constructor (method, url, timeout) {
super(timeout)
this.name = 'FetchTimeoutError'
this.message = `${method} ${url}: timeout after ${timeout / 1000}s`
}
}
export async function fetchWithTimeout (resource, { timeout = 1000, ...options } = {}) {
const controller = new AbortController()
const id = setTimeout(() => controller.abort(), timeout)
const response = await fetch(resource, {
...options,
signal: controller.signal
})
clearTimeout(id)
return response
try {
return await fetch(resource, {
...options,
signal: AbortSignal.timeout(timeout)
})
} catch (err) {
if (err.name === 'TimeoutError') {
// use custom error message
throw new FetchTimeoutError('GET', resource, timeout)
}
throw err
}
}
class LRUCache {

View File

@ -128,6 +128,13 @@ function tzOffset (tz) {
return targetOffsetHours
}
export class TimeoutError extends Error {
constructor (timeout) {
super(`timeout after ${timeout / 1000}s`)
this.name = 'TimeoutError'
}
}
function timeoutPromise (timeout) {
return new Promise((resolve, reject) => {
// if no timeout is specified, never settle