Skip to content

Commit

Permalink
refactor impl and rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Aug 16, 2023
1 parent 5f95a88 commit dece4c7
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ await ofetch('/url', { ignoreResponseError: true })

## ✔️ Auto Retry

`ofetch` Automatically retries the request if an error happens and if response status code is included in `retryStatusCodes` list.

Default is `1` retry, except for `POST`, `PUT`, `PATCH` and `DELETE` methods ofetch does not retry.
`ofetch` Automatically retries the request if an error happens and if response status code is included in `retryStatusCodes` list:

**Retry status codes:**

Expand All @@ -114,9 +112,16 @@ Default is `1` retry, except for `POST`, `PUT`, `PATCH` and `DELETE` methods ofe
- `503` - Service Unavailable
- `504` - Gateway Timeout

You can specifcy amount of retires and delay between them using `retry` and `retryDelay` options.

Default for `retry` is `1` retry, except for `POST`, `PUT`, `PATCH` and `DELETE` methods ofetch does not retry.

Default for `retryDelay` is zero ms.

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

Expand Down
9 changes: 8 additions & 1 deletion src/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ export interface FetchOptions<R extends ResponseType = ResponseType>
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,7 +89,7 @@ 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
Expand All @@ -103,6 +106,10 @@ export function createFetch(globalOptions: CreateFetchOptions): $Fetch {

const responseCode = (context.response && context.response.status) || 500;
if (retries > 0 && retryStatusCodes.has(responseCode)) {
const retryDelay = context.options.retryDelay || 0;
if (retryDelay > 0) {
await new Promise((resolve) => setTimeout(resolve, retryDelay));
}
return $fetchRaw(context.request, {
...context.options,
retry: retries - 1,
Expand Down
21 changes: 20 additions & 1 deletion test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ describe("ofetch", () => {
eventHandler(() =>
createError({ status: 403, statusMessage: "Forbidden" })
)
)
.use(
"/408",
eventHandler(() => createError({ status: 408 }))
);

listener = await listen(toNodeListener(app));
});

Expand Down Expand Up @@ -135,7 +140,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 +201,20 @@ describe("ofetch", () => {
expect(error.request).to.equal(getURL("404"));
});

it("retry with delay", async () => {
const slow = $fetch<string>(getURL("408"), {
retry: 2,
retryDelay: 100,
}).catch(() => "slow");
const fast = $fetch<string>(getURL("408"), {
retry: 2,
retryDelay: 1,
}).catch(() => "fast");

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 dece4c7

Please sign in to comment.