Skip to content

Commit

Permalink
feat: implement retry delay
Browse files Browse the repository at this point in the history
  • Loading branch information
Hebilicious committed Aug 8, 2023
1 parent 41c3b56 commit d35226b
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 4 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ await ofetch('/url', { ignoreResponseError: true })

```ts
await ofetch('http://google.com/404', {
retry: 3
retry: 3,
retryDelay: 500, //ms, default to 100
})
```

Expand Down
9 changes: 7 additions & 2 deletions src/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ export interface FetchOptions<R extends ResponseType = ResponseType>
responseType?: R;
response?: boolean;
retry?: number | false;

/**
* Delay between retries in milliseconds.
*/
retryDelay?: number;
onRequest?(context: FetchContext): Promise<void> | void;
onRequestError?(
context: FetchContext & { error: Error }
Expand Down Expand Up @@ -86,14 +89,15 @@ const retryStatusCodes = new Set([
export function createFetch(globalOptions: CreateFetchOptions): $Fetch {
const { fetch, Headers } = globalOptions;

function onError(context: FetchContext): Promise<FetchResponse<any>> {
async function onError(context: FetchContext): Promise<FetchResponse<any>> {
// Is Abort
// If it is an active abort, it will not retry automatically.
// https://developer.mozilla.org/en-US/docs/Web/API/DOMException#error_names
const isAbort =
(context.error && context.error.name === "AbortError") || false;
// Retry
if (context.options.retry !== false && !isAbort) {
const retryDelay = context.options.retryDelay || 100;
let retries;
if (typeof context.options.retry === "number") {
retries = context.options.retry;
Expand All @@ -103,6 +107,7 @@ export function createFetch(globalOptions: CreateFetchOptions): $Fetch {

const responseCode = (context.response && context.response.status) || 500;
if (retries > 0 && retryStatusCodes.has(responseCode)) {
await new Promise((resolve) => setTimeout(resolve, retryDelay));
return $fetchRaw(context.request, {
...context.options,
retry: retries - 1,
Expand Down
15 changes: 14 additions & 1 deletion test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ describe("ofetch", () => {
const { headers } = await $fetch(getURL("post"), {
method: "POST",
body: { num: 42 },
headers: sentHeaders,
headers: sentHeaders as HeadersInit,
});
expect(headers).to.include({ "x-header": "1" });
expect(headers).to.include({ accept: "application/json" });
Expand Down Expand Up @@ -196,6 +196,19 @@ describe("ofetch", () => {
expect(error.request).to.equal(getURL("404"));
});

it("retry with delay", async () => {
const fast = $fetch<string>(getURL("404"), {
retry: 2,
retryDelay: 1,
}).catch(() => "fast");
const slow = $fetch<string>(getURL("404"), {
retry: 2,
retryDelay: 100,
}).catch(() => "slow");
const race = await Promise.race([slow, fast]);
expect(race).to.equal("fast");
});

it("abort with retry", () => {
const controller = new AbortController();
async function abortHandle() {
Expand Down

0 comments on commit d35226b

Please sign in to comment.