Skip to content

Instantly share code, notes, and snippets.

@imaginamundo
Created August 19, 2025 22:05
Show Gist options
  • Select an option

  • Save imaginamundo/cc946479e36359c370990e901c4ba424 to your computer and use it in GitHub Desktop.

Select an option

Save imaginamundo/cc946479e36359c370990e901c4ba424 to your computer and use it in GitHub Desktop.
Fetch wrapper with timeout with tuple response
async function fetchWithTimeout(
resource: RequestInfo | URL,
options: RequestInit & { timeout?: number } = {}
): Promise<Response> {
const { timeout = 3000 } = options;
try {
const response = await fetch(resource, {
...options,
signal: AbortSignal.timeout(timeout),
});
return response;
} catch (error: unknown) {
if (error instanceof Error) {
if (error.name === 'TimeoutError' || error.name === 'AbortError') {
console.log(`Request to ${resource.toString()} timed out after ${timeout}ms.`);
}
} else {
console.log('An unexpected non-error value was thrown:', error);
}
throw error;
}
}
export default async function request<T>(
resource: RequestInfo | URL,
options: RequestInit & { timeout?: number } = {}
): Promise<[T, null] | [null, Error]> {
try {
const response = await fetchWithTimeout(resource, options);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
}
const data = (await response.json()) as T;
return [data, null];
} catch (error: unknown) {
if (error instanceof Error) {
return [null, error];
}
return [null, new Error('An unexpected non-error value was thrown')];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment