fetchJsonWithTimeoutSignal
JavaScript
// Fetches JSON with a hard timeout and explicit HTTP/JSON error handling.
export async function fetchJson(url, { timeoutMs = 10_000, headers = {} } = {}) {
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
throw new RangeError('timeoutMs must be a positive number');
}
let response;
try {
response = await fetch(url, {
method: 'GET',
headers: { Accept: 'application/json', ...headers },
signal: AbortSignal.timeout(timeoutMs),
});
} catch (error) {
if (error.name === 'TimeoutError') {
throw new Error(`GET ${url} timed out after ${timeoutMs} ms`, { cause: error });
}
throw error;
}
if (!response.ok) {
throw new Error(`GET ${url} failed with HTTP ${response.status}`);
}
const text = await response.text();
try {
return text === '' ? null : JSON.parse(text);
} catch (error) {
throw new SyntaxError(`GET ${url} returned invalid JSON`, { cause: error });
}
}