Skip to content

Instantly share code, notes, and snippets.

@belsrc
Last active March 29, 2022 13:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save belsrc/2e108363f36485c7038bdf871affd121 to your computer and use it in GitHub Desktop.
Save belsrc/2e108363f36485c7038bdf871affd121 to your computer and use it in GitHub Desktop.
Extended Fetch function
type fetchOptions = {
timeout?: number,
retries?: number,
cancelable?: boolean,
method?: string,
mode?: RequestMode,
cache?: RequestCache,
credentials?: RequestCredentials,
headers?: HeadersInit,
redirect?: RequestRedirect,
referrer?: string,
referrerPolicy?: ReferrerPolicy,
integrity?: string,
keepalive?: boolean,
signal?: AbortSignal,
body?: BodyInit,
};
type CancelCallTuple = [Promise<void | Response>, () => void];
const timeoutThrow = (timeout: number): Promise<void> =>
new Promise((_, reject) => {
setTimeout(() => reject(new Error('timeout')), timeout);
});
const call = async (url: string, options: fetchOptions = {}, retryCount = 0): Promise<void | Response> => {
const { timeout, retries = 3, ...remainingOptions } = options;
try {
if(timeout) {
return await Promise.race([
fetch(url, remainingOptions),
timeoutThrow(timeout),
]);
}
return await fetch(url, remainingOptions);
}
catch(error) {
if(retryCount < retries) {
return call(url, options, retryCount + 1);
}
throw error;
}
};
const callWithCancel = (url: string, options: fetchOptions = {}): CancelCallTuple => {
const controller = new AbortController();
const res = call(
url,
{ ...options, signal: controller.signal },
);
return [res, controller.abort];
};
/* {
cancelable: true,
retries: 3,
timeout: 5000,
...standardFetchOptions,
} */
const fetchUrl = (url: string, options: fetchOptions = {}) => {
const { cancelable, ...remainingOptions } = options;
if(cancelable) {
return callWithCancel(url, remainingOptions);
}
return call(url, remainingOptions);
}
/*
const result = await fetchUrl('https://www.google.com');
const result = await fetchUrl('https://www.google.com', { retries: 3, timeout: 5000 });
const [result, cancel] = fetchUrl('https://www.google.com', { cancelable: true });
const [result, cancel] = fetchUrl('https://www.google.com', {
cancelable: true,
retries: 3,
timeout: 1000
});
// and, if needed...
cancel();
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment