09 Fetch
Fetch API
The JavaScript fetch API is a modern replacement for XMLHttpRequest. It is a promise-based API that allows you to make HTTP requests from JavaScript.
fetch() has the following basic structure:
fetch(url, options)
.then(response => {
// handle response
response.json() // e.g. get body as JSON
})
.then(data => {
// json() returns promise
console.log(data) // log the response body to the console
})
.catch(error => {
// handle error
console.error(error)
});
fetch() returns a promise that resolves to a response object.
A promise represents the eventual completion (or failure) of an asynchronous operation.
It can be in one of the following states:
- pending: initial state, neither fulfilled nor rejected
- fulfilled: operation completed successfully
- rejected: operation failed
fetch() does not reject if the HTTP status code indicates an error!
Request
A request object can be passed to fetch() as the first argument, which contains all information about the request.
The request object can be created like this:
const request = new Request("https://server/api.json", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({foo: "bar"})
});
fetch(request)
.then(response => {
// handle response
})
.catch(error => {
// handle error
});
// which is equivalent to:
fetch("https://server/api.json", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({foo: "bar"})
})
.then(response => {
// handle response
})
.catch(error => {
// handle error
});
Response
If the request was successful, fetch() returns a response object.
(Successful means that the request could be sent and a response was received).
The response object has the following structure:
{
ok: true, // true if the status code is in the range 200-299
status: 200, // HTTP status code
statusText: "OK", // HTTP status text
headers: Headers, // HTTP headers
body: ReadableStream, // response body
...
}
The response body can be accessed using the following methods:
response.body: returns a ReadableStream that can be used to read the response bodyresponse.json(): returns a promise that resolves to the response body as JSONresponse.text(): returns a promise that resolves to the response body as textresponse.blob(): returns a promise that resolves to the response body as a Blobresponse.arrayBuffer(): returns a promise that resolves to the response body as an ArrayBufferresponse.formData(): returns a promise that resolves to the response body as FormData
Async/Await
In the previous examples, the promise was handled using then() and catch().
This can be simplified using the async and await keywords.
async is used to mark a function as asynchronous (making await available).
await is used to wait for a promise to resolve.
The previous example can be rewritten like this:
async function fetchExample() {
try {
const response = await fetch("https://server/api.json", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({foo: "bar"})
});
// handle response
} catch (error) {
// handle error
}
}
// or, using arrow functions:
const fetchExample = async () => {
try {
const response = await fetch("https://server/api.json", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({foo: "bar"})
});
// handle response
} catch (error) {
// handle error
}
}
Same Origin Policy
The same origin policy (SOP) is a browser security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin. The SOP will prevent the client (React) from communicating with the server (REST API). To allow the client to communicate with the server, the server has to send the following header:
Access-Control-Allow-Origin: *
Cross-Origin Resource Sharing (CORS)
This is called Cross-Origin Resource Sharing (CORS).
The * means that the server allows all origins to access the resource.
(This is not recommended for production environments.)
CORS also allows for more granular control over which origins are allowed to access which resources in which way. Other headers that can be used to control CORS are:
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Credentials: true