From 725ed08298e3e78469dcf7fa5726beec975122c9 Mon Sep 17 00:00:00 2001 From: arlo Date: Thu, 11 Jan 2024 15:14:08 +0800 Subject: [PATCH 1/5] feat!: add timeout reason for timeout AbortSignal --- src/fetch.ts | 4 +++- test/index.test.ts | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/fetch.ts b/src/fetch.ts index c0021c0..86c880d 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -46,6 +46,7 @@ export function createFetch(globalOptions: CreateFetchOptions = {}): $Fetch { context.error.name === "AbortError" && !context.options.timeout) || false; + // Retry if (context.options.retry !== false && !isAbort) { let retries; @@ -152,7 +153,8 @@ export function createFetch(globalOptions: CreateFetchOptions = {}): $Fetch { // TODO: Can we merge signals? if (!context.options.signal && context.options.timeout) { const controller = new AbortController(); - setTimeout(() => controller.abort(), context.options.timeout); + const reason = new Error("Request timeout", { cause: "timeout" }); + setTimeout(() => controller.abort(reason), context.options.timeout); context.options.signal = controller.signal; } diff --git a/test/index.test.ts b/test/index.test.ts index de25338..cf277fd 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -323,6 +323,15 @@ describe("ofetch", () => { expect(race).to.equal("timeout"); }); + it("aborting on timeout message", async () => { + await $fetch(getURL("timeout"), { + timeout: 100, + retry: 0, + }).catch((error) => { + expect(error.cause.cause).to.equal("timeout"); + }); + }); + it("deep merges defaultOptions", async () => { const _customFetch = $fetch.create({ query: { From 9327dfb891bf0a895bec654d50a2ed99bac36625 Mon Sep 17 00:00:00 2001 From: arlo Date: Thu, 11 Jan 2024 15:14:53 +0800 Subject: [PATCH 2/5] chore: update --- src/fetch.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/fetch.ts b/src/fetch.ts index 86c880d..1b4386f 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -46,7 +46,6 @@ export function createFetch(globalOptions: CreateFetchOptions = {}): $Fetch { context.error.name === "AbortError" && !context.options.timeout) || false; - // Retry if (context.options.retry !== false && !isAbort) { let retries; @@ -139,7 +138,7 @@ export function createFetch(globalOptions: CreateFetchOptions = {}): $Fetch { // ReadableStream Body ("pipeTo" in (context.options.body as ReadableStream) && typeof (context.options.body as ReadableStream).pipeTo === - "function") || + "function") || // Node.js Stream Body typeof (context.options.body as Readable).pipe === "function" ) { From cefdf2db815271a22e1a2858a531c2afd71a912a Mon Sep 17 00:00:00 2001 From: Arlo Date: Thu, 11 Jan 2024 15:19:46 +0800 Subject: [PATCH 3/5] chore: update --- src/fetch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fetch.ts b/src/fetch.ts index 1b4386f..f6473f2 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -138,7 +138,7 @@ export function createFetch(globalOptions: CreateFetchOptions = {}): $Fetch { // ReadableStream Body ("pipeTo" in (context.options.body as ReadableStream) && typeof (context.options.body as ReadableStream).pipeTo === - "function") || + "function") || // Node.js Stream Body typeof (context.options.body as Readable).pipe === "function" ) { From d7bc51a23bbb32f08772b39d7e1beabde50694ad Mon Sep 17 00:00:00 2001 From: Arlo Date: Thu, 11 Jan 2024 15:21:39 +0800 Subject: [PATCH 4/5] chore: update --- test/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.test.ts b/test/index.test.ts index cf277fd..04e6a2e 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -323,7 +323,7 @@ describe("ofetch", () => { expect(race).to.equal("timeout"); }); - it("aborting on timeout message", async () => { + it("aborting on timeout reason", async () => { await $fetch(getURL("timeout"), { timeout: 100, retry: 0, From 871ed95f1388097efdde1e2eaa81bd74410dec64 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 16 May 2024 11:57:20 +0200 Subject: [PATCH 5/5] error compatibility with `AbortSignal.timeout` --- src/fetch.ts | 8 ++++++-- test/index.test.ts | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/fetch.ts b/src/fetch.ts index 41f5411..61d858a 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -157,8 +157,12 @@ export function createFetch(globalOptions: CreateFetchOptions = {}): $Fetch { if (!context.options.signal && context.options.timeout) { const controller = new AbortController(); abortTimeout = setTimeout(() => { - const reason = new Error("Request timeout", { cause: "timeout" }); - controller.abort(reason); + const error = new Error( + "[TimeoutError]: The operation was aborted due to timeout" + ); + error.name = "TimeoutError"; + (error as any).code = 23; // DOMException.TIMEOUT_ERR + controller.abort(error); }, context.options.timeout); context.options.signal = controller.signal; } diff --git a/test/index.test.ts b/test/index.test.ts index 5fd144a..41446af 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -342,7 +342,11 @@ describe("ofetch", () => { timeout: 100, retry: 0, }).catch((error) => { - expect(error.cause.cause).to.equal("timeout"); + expect(error.cause.message).to.include( + "The operation was aborted due to timeout" + ); + expect(error.cause.name).to.equal("TimeoutError"); + expect(error.cause.code).to.equal(DOMException.TIMEOUT_ERR); }); });