The Fetch API provides a JavaScript interface for accessing and manipulating parts of the protocol, such as requests and responses. It also provides a global fetch() method that provides an easy, logical way to fetch resources asynchronously across the network.
Unlike XMLHttpRequest that is a callback-based API, Fetch is promise-based and provides a better alternative that can be easily used in service workers. Fetch also integrates advanced HTTP concepts such as CORS and other extensions to HTTP.
A basic fetch request looks like this:
async function logMovies() {
const response = await fetch("http://example.com/movies.json");
const movies = await response.json();
console.log(movies);
}
Here we are fetching a JSON file across the network, parsing it, and printing the data to the console. The simplest use of fetch()
takes one argument — the path to the resource you want to fetch — and does not directly return the JSON response body but instead returns a promise that resolves with a Response
object.
The Response
object, in turn, does not directly contain the actual JSON response body but is instead a representation of the entire HTTP response. So, to extract the JSON body content from the Response
object, we use the json()
method, which returns a second promise that resolves with the result of parsing the response body text as JSON.
Fetch requests are controlled by the connect-src
directive of Content Security Policy rather than the directive of the resources it's retrieving.
Supplying request options
The fetch()
method can optionally accept a second parameter, an init
object that allows you to control a number of different settings:
See fetch()
for the full options available, and more details.
// Example POST method implementation:
async function postData(url = "", data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: "POST", // *GET, POST, PUT, DELETE, etc.
mode: "cors", // no-cors, *cors, same-origin
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
credentials: "same-origin", // include, *same-origin, omit
headers: {
"Content-Type": "application/json",
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: "follow", // manual, *follow, error
referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(data), // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData("https://example.com/answer", { answer: 42 }).then((data) => {
console.log(data); // JSON data parsed by `data.json()` call
});
Note that mode: "no-cors"
only allows a limited set of headers in the request:
Accept
Accept-Language
Content-Language
Content-Type
with a value ofapplication/x-www-form-urlencoded
,multipart/form-data
, ortext/plain
Aborting a fetch
To abort incomplete fetch()
operations, use the AbortController
and AbortSignal
interfaces.
const controller = new AbortController();
const signal = controller.signal;
const url = "video.mp4";
const downloadBtn = document.querySelector("#download");
const abortBtn = document.querySelector("#abort");
downloadBtn.addEventListener("click", async () => {
try {
const response = await fetch(url, { signal });
console.log("Download complete", response);
} catch (error) {
console.error(`Download error: ${error.message}`);
}
});
abortBtn.addEventListener("click", () => {
controller.abort();
console.log("Download aborted");
});
Sending a request with credentials included
To cause browsers to send a request with credentials included on both same-origin and cross-origin calls, add credentials: 'include'
to the init
object you pass to the fetch()
method.
fetch("https://example.com", {
credentials: "include",
});
If you only want to send credentials if the request URL is on the same origin as the calling script, add credentials: 'same-origin'
.
// The calling script is on the origin 'https://example.com'
fetch("https://example.com", {
credentials: "same-origin",
});
If you only want to send credentials if the request URL is on the same origin as the calling script, add credentials: 'same-origin'
.
// The calling script is on the origin 'https://example.com'
fetch("https://example.com", {
credentials: "same-origin",
});
To instead ensure browsers don’t include credentials in the request, use credentials: 'omit'
.
fetch("https://example.com", {
credentials: "omit",
});