From 5577273a6489e97277c4853e6772c4556d86e4b8 Mon Sep 17 00:00:00 2001 From: wbamberg Date: Wed, 3 Jul 2024 16:09:08 -0700 Subject: [PATCH] Document 2 more exceptions; explain about aborting requests after fetch fulfills --- files/en-us/web/api/abortcontroller/index.md | 36 ++++++++++---- files/en-us/web/api/abortsignal/index.md | 49 +++++++++++++------ .../web/api/fetch_api/using_fetch/index.md | 17 +++++++ .../web/api/response/arraybuffer/index.md | 6 ++- files/en-us/web/api/response/blob/index.md | 4 +- files/en-us/web/api/response/bytes/index.md | 4 +- .../en-us/web/api/response/formdata/index.md | 1 + files/en-us/web/api/response/json/index.md | 4 +- files/en-us/web/api/response/text/index.md | 4 +- 9 files changed, 97 insertions(+), 28 deletions(-) diff --git a/files/en-us/web/api/abortcontroller/index.md b/files/en-us/web/api/abortcontroller/index.md index e5409cb3c043c5e..09760ed35d46c77 100644 --- a/files/en-us/web/api/abortcontroller/index.md +++ b/files/en-us/web/api/abortcontroller/index.md @@ -36,6 +36,8 @@ We first create a controller using the {{domxref("AbortController.AbortControlle When the [fetch request](/en-US/docs/Web/API/fetch) is initiated, we pass in the `AbortSignal` as an option inside the request's options object (the `{signal}` below). This associates the signal and controller with the fetch request and allows us to abort it by calling {{domxref("AbortController.abort()")}}, as seen below in the second event listener. +When `abort()` is called, the `fetch()` promise rejects with a `DOMException` named `AbortError`. + ```js let controller; const url = "video.mp4"; @@ -52,20 +54,36 @@ abortBtn.addEventListener("click", () => { } }); -function fetchVideo() { +async function fetchVideo() { controller = new AbortController(); const signal = controller.signal; - fetch(url, { signal }) - .then((response) => { - console.log("Download complete", response); - }) - .catch((err) => { - console.error(`Download error: ${err.message}`); - }); + + try { + const response = await fetch(url, { signal }); + console.log("Download complete", response); + // process response further + } catch (err) { + console.error(`Download error: ${err.message}`); + } } ``` -> **Note:** When `abort()` is called, the `fetch()` promise rejects with a `DOMException` named `AbortError`. +If the request is aborted after the `fetch()` call has been fulfilled but before the response body has been read, then attempting to read the response body will reject with an `AbortError` exception. + +```js +async function get() { + const controller = new AbortController(); + const request = new Request("https://example.org/get", { + signal: controller.signal, + }); + + const response = await fetch(request); + controller.abort(); + // The next line will throw `AbortError` + const text = await response.text(); + console.log(text); +} +``` You can find a [full working example on GitHub](https://github.com/mdn/dom-examples/tree/main/abort-api); you can also see it [running live](https://mdn.github.io/dom-examples/abort-api/). diff --git a/files/en-us/web/api/abortsignal/index.md b/files/en-us/web/api/abortsignal/index.md index e3882edae74ad22..320b8f7c51ed841 100644 --- a/files/en-us/web/api/abortsignal/index.md +++ b/files/en-us/web/api/abortsignal/index.md @@ -59,33 +59,54 @@ We first create an abort controller using the {{domxref("AbortController.AbortCo When the [fetch request](/en-US/docs/Web/API/fetch) is initiated, we pass in the `AbortSignal` as an option inside the request's options object (the `{signal}` below). This associates the signal and controller with the fetch request, and allows us to abort it by calling {{domxref("AbortController.abort()")}}. Below you can see that the fetch operation is aborted in the second event listener, which triggered when the abort button (`abortBtn`) is clicked. -```js -const controller = new AbortController(); -const signal = controller.signal; +When `abort()` is called, the `fetch()` promise rejects with a `DOMException` named `AbortError`. +```js +let controller; const url = "video.mp4"; + const downloadBtn = document.querySelector(".download"); const abortBtn = document.querySelector(".abort"); downloadBtn.addEventListener("click", fetchVideo); abortBtn.addEventListener("click", () => { - controller.abort(); - console.log("Download aborted"); + if (controller) { + controller.abort(); + console.log("Download aborted"); + } }); -function fetchVideo() { - fetch(url, { signal }) - .then((response) => { - console.log("Download complete", response); - }) - .catch((err) => { - console.error(`Download error: ${err.message}`); - }); +async function fetchVideo() { + controller = new AbortController(); + const signal = controller.signal; + + try { + const response = await fetch(url, { signal }); + console.log("Download complete", response); + // process response further + } catch (err) { + console.error(`Download error: ${err.message}`); + } } ``` -> **Note:** When `abort()` is called, the `fetch()` promise rejects with an "`AbortError`" `DOMException`. +If the request is aborted after the `fetch()` call has been fulfilled but before the response body has been read, then attempting to read the response body will reject with an `AbortError` exception. + +```js +async function get() { + const controller = new AbortController(); + const request = new Request("https://example.org/get", { + signal: controller.signal, + }); + + const response = await fetch(request); + controller.abort(); + // The next line will throw `AbortError` + const text = await response.text(); + console.log(text); +} +``` You can find a [full working example on GitHub](https://github.com/mdn/dom-examples/tree/main/abort-api); you can also see it [running live](https://mdn.github.io/dom-examples/abort-api/). diff --git a/files/en-us/web/api/fetch_api/using_fetch/index.md b/files/en-us/web/api/fetch_api/using_fetch/index.md index ba58a68d65cffc3..10e3df3cbdc7d8e 100644 --- a/files/en-us/web/api/fetch_api/using_fetch/index.md +++ b/files/en-us/web/api/fetch_api/using_fetch/index.md @@ -294,6 +294,23 @@ cancelButton.addEventListener("click", () => { }); ``` +If the request is aborted after the `fetch()` call has been fulfilled but before the response body has been read, then attempting to read the response body will reject with an `AbortError` exception. + +```js +async function get() { + const controller = new AbortController(); + const request = new Request("https://example.org/get", { + signal: controller.signal, + }); + + const response = await fetch(request); + controller.abort(); + // The next line will throw `AbortError` + const text = await response.text(); + console.log(text); +} +``` + ## Handling the response As soon as the browser has received the response status and headers from the server (and potentially before the response body itself has been received), the promise returned by `fetch()` is fulfilled with a {{domxref("Response")}} object. diff --git a/files/en-us/web/api/response/arraybuffer/index.md b/files/en-us/web/api/response/arraybuffer/index.md index 7a3e15a676e9d3f..b4e95d956da8ff1 100644 --- a/files/en-us/web/api/response/arraybuffer/index.md +++ b/files/en-us/web/api/response/arraybuffer/index.md @@ -28,8 +28,12 @@ A promise that resolves with an {{jsxref("ArrayBuffer")}}. ### Exceptions +- {{domxref("DOMException")}} `AbortError` + - : The request was [aborted](/en-US/docs/Web/API/Fetch_API/Using_Fetch#canceling_a_request). - {{jsxref("TypeError")}} - - : The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - : Thrown for one of the following reasons: + - The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - There is an error decoding the body content (for example, because the {{httpheader("Content-Encoding")}} header is incorrect). - {{jsxref("RangeError")}} - : There is a problem creating the associated `ArrayBuffer`. For example, if the data size is more than [`Number.MAX_SAFE_INTEGER`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER). diff --git a/files/en-us/web/api/response/blob/index.md b/files/en-us/web/api/response/blob/index.md index 90db0ea784dd626..83c7b419544d838 100644 --- a/files/en-us/web/api/response/blob/index.md +++ b/files/en-us/web/api/response/blob/index.md @@ -35,7 +35,9 @@ A promise that resolves with a {{domxref("Blob")}}. ### Exceptions - {{jsxref("TypeError")}} - - : The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - : Thrown for one of the following reasons: + - The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - There is an error decoding the body content (for example, because the {{httpheader("Content-Encoding")}} header is incorrect). ## Examples diff --git a/files/en-us/web/api/response/bytes/index.md b/files/en-us/web/api/response/bytes/index.md index d7ac5ce3d5f5d47..740dd30aaf2d6df 100644 --- a/files/en-us/web/api/response/bytes/index.md +++ b/files/en-us/web/api/response/bytes/index.md @@ -28,7 +28,9 @@ A promise that resolves with an {{jsxref("Uint8Array")}}. ### Exceptions - {{jsxref("TypeError")}} - - : The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - : Thrown for one of the following reasons: + - The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - There is an error decoding the body content (for example, because the {{httpheader("Content-Encoding")}} header is incorrect). - {{jsxref("RangeError")}} - : There is a problem creating the associated `ArrayBuffer`. For example, if the data size is more than [`Number.MAX_SAFE_INTEGER`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER). diff --git a/files/en-us/web/api/response/formdata/index.md b/files/en-us/web/api/response/formdata/index.md index ade36e73e9cd372..a2d67cc10b85ef3 100644 --- a/files/en-us/web/api/response/formdata/index.md +++ b/files/en-us/web/api/response/formdata/index.md @@ -36,6 +36,7 @@ A {{jsxref("Promise")}} that resolves with a {{domxref("FormData")}} object. - {{jsxref("TypeError")}} - : Thrown for one of the following reasons: - The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - There is an error decoding the body content (for example, because the {{httpheader("Content-Encoding")}} header is incorrect). - The {{glossary("MIME")}} type of the body cannot be determined from the {{httpheader("Content-Type")}} headers included in the response. - The body cannot be parsed as a `FormData` object. diff --git a/files/en-us/web/api/response/json/index.md b/files/en-us/web/api/response/json/index.md index 8d11f0f68404e1f..1b351bdf74585a6 100644 --- a/files/en-us/web/api/response/json/index.md +++ b/files/en-us/web/api/response/json/index.md @@ -32,7 +32,9 @@ anything that can be represented by JSON — an object, an array, a string, a nu ### Exceptions - {{jsxref("TypeError")}} - - : The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - : Thrown for one of the following reasons: + - The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - There is an error decoding the body content (for example, because the {{httpheader("Content-Encoding")}} header is incorrect). - {{jsxref("SyntaxError")}} - : The response body cannot be parsed as JSON. diff --git a/files/en-us/web/api/response/text/index.md b/files/en-us/web/api/response/text/index.md index bfb59e3178a09d7..63040f036c68d19 100644 --- a/files/en-us/web/api/response/text/index.md +++ b/files/en-us/web/api/response/text/index.md @@ -29,7 +29,9 @@ A Promise that resolves with a {{jsxref("String")}}. ### Exceptions - {{jsxref("TypeError")}} - - : The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - : Thrown for one of the following reasons: + - The response body is [disturbed or locked](/en-US/docs/Web/API/Fetch_API/Using_Fetch#locked_and_disturbed_streams). + - There is an error decoding the body content (for example, because the {{httpheader("Content-Encoding")}} header is incorrect). ## Examples