Fetch API and Client-Side Requests
Learning Objectives
- You know the Fetch API and how to make GET and POST requests with it.
- You know how to make client-side API requests with Fetch from Svelte components.
Fetch API
Fetch API is a standard JavaScript API for making HTTP requests programmatically from JavaScript code. The key method of the API is fetch, which allows creating and executing a request, returning a Response object.
The
fetchmethod is asynchronous and returns a Promise, we resolve the promise withawait.
GET request
To make an HTTP GET request with fetch, we simply call fetch(url), passing it the URL to which the request is sent as a parameter.
In the following example, we make a GET request to the address https://wsd-todos-api.deno.dev/todos, and then ask for the response data in JSON format using the json method of the response object.
const API_URL = "https://wsd-todos-api.deno.dev";
const response = await fetch(`${API_URL}/todos`);
const jsonData = await response.json();
console.log(jsonData);
When the above program is run with Deno, the output looks as follows.
$ deno run --allow-net app-test.js
[
{ id: 1, name: "Introduction to Web Applications", done: true },
{ id: 2, name: "Databases and Data Validation", done: true },
{ id: 3, name: "Client-Side Development", done: true },
{ id: 4, name: "Client-Server Interaction", done: false }
]
That is, to make a GET request, we simply call the fetch method with the target URL, and then parse the response using the json method of the response object.
POST request
The HTTP POST request is typically used to send data to the server, such as creating a new resource.
To make a POST request with fetch, we need to explicitly provide the request method, as well as optionally the headers and the body of the request. These are provided as an object to the fetch method, which is passed as the second parameter to the method.
The following example outlines the structure of a POST request with fetch.
const API_URL = "URL"; // the URL to which the request is sent
const data = {}; // the data to be sent in the request body
const response = await fetch(API_URL, {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
});
When sending JSON, convert the data object to a JSON string using JSON.stringify and set Content-Type header to application/json.
As an example, if we want to send a todo object to a server, we could define the data object as follows.
const data = {
name: "Evolution of Web Development",
done: false,
};
And, then, we could make the POST request with fetch. Given that we want to send the todo object to the address https://wsd-todos-api.deno.dev/todos, the complete POST request would look as follows.
const API_URL = "https://wsd-todos-api.deno.dev";
const data = {
name: "Evolution of Web Development",
done: false,
};
const response = await fetch(`${API_URL}/todos`, {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
});
The fetch method returns a response object, which contains information about the response from the server. This includes the status code, headers, and the response body. Like earlier, when making a GET request, we can parse the response body as JSON using the json method of the response object.
const API_URL = "https://wsd-todos-api.deno.dev";
const data = {
name: "Evolution of Web Development",
done: false,
};
const response = await fetch(`${API_URL}/todos`, {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
});
const jsonData = await response.json();
console.log(jsonData);
Running the above example provides the following output.
$ deno run --allow-net app.js
{ name: "Evolution of Web Development", done: false, id: 5 }
Response properties
The response object returned by the fetch method has several useful properties that can be used to inspect the response from the server. Some of the most commonly used properties include:
status: The HTTP status code of the response (e.g., 200 for success, 404 for not found).statusText: The status message corresponding to the status code (e.g., “OK” for 200).headers: An instance of Headers containing the response headers.ok: A boolean indicating whether the response was successful (status code in the range 200-299).
As an example, if we wish to parse the JSON data from the response only if the request was successful, we could do it as follows.
const API_URL = "https://wsd-todos-api.deno.dev";
const response = await fetch(`${API_URL}/todos`);
if (response.ok) {
const jsonData = await response.json();
console.log(jsonData);
} else {
console.error("Error: " + response.status);
}
Any type of request method can be used with the Fetch API, as we can define the method in the method property of the object that is passed to the fetch method.
Svelte and Fetch API
The Fetch API is a standard JavaScript API that can be used in any JavaScript environment that supports standard JavaScript APIs. This includes Svelte components, where we can use the Fetch API to make HTTP requests to interact with server-side APIs.
Retrieving data
The following example outlines a component that can be used to make a GET request with fetch. The function makes a GET request to the path /todos/1 of the API, returning a single todo object in JSON format. Once the request has been made, the todo object is parsed into a JavaScript object, and assigned to the todo variable.
When the button on the page is pressed, the function is called. After the function finishes and the value of todo changes, the todo is shown on the page.
<script>
const API_URL = "https://wsd-todos-api.deno.dev";
let todo = $state({});
const getTodo = async () => {
const response = await fetch(`${API_URL}/todos/1`);
todo = await response.json();
};
</script>
<button onclick={getTodo}>Fetch todo</button>
<br />
<p>Todo is: {todo.name}</p>
As the todo is initially an empty object, the text Todo is: is shown on the page before the button is pressed. After the button is pressed, the todo is fetched from the API, and the name of the todo is shown on the page.
Posting data
Similarly, we could create a component for making a POST request with fetch. Below, the function addTodo makes a POST request to the path “/todos” of the API, which is used to add a new todo. The function would send a todo object to the address, and once the response is received, the id of the new todo is shown to the user.
<script>
const API_URL = "https://wsd-todos-api.deno.dev";
let todo = $state({});
const addTodo = async () => {
const data = {
name: "Evolution of Web Development",
done: false,
};
const response = await fetch(`${API_URL}/todos`, {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
});
todo = await response.json();
};
</script>
<button onclick={addTodo}>Add todo</button>
<br />
<p>The id of the new todo is: {todo.id}</p>
While the above example demonstrates creating a POST request with static data, we could also create a form that allows the user to input the data.
Posting a form
To post a form with fetch, we first need to collect the data from the form fields. As discussed in the previous chapter, we can process the form submission in Svelte by attaching an event handler to the onsubmit event of the form. Then, when the form submission event is triggered, we can collect the data from the form fields using the FormData API, construct a data object from the form data, serialize it with JSON.stringify, and send it to the server with fetch.
<script>
const API_URL = "https://wsd-todos-api.deno.dev";
let todo = $state({});
const addTodo = async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = Object.fromEntries(formData);
data.done = false;
const response = await fetch(`${API_URL}/todos`, {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
});
todo = await response.json();
};
</script>
<form onsubmit={addTodo}>
<label>
Todo name
<input
id="name"
name="name"
type="text"
placeholder="Enter todo name"
/>
</label>
<input type="submit" value="Submit form" />
</form>
<br />
<p>The id of the new todo is: {todo.id}</p>
Summary
In summary:
- The Fetch API provides a standard way to make HTTP requests in JavaScript.
fetch(url)performs GET requests; for POST (or other methods), pass an options object as the second parameter.- Responses can be inspected using properties like
ok,status, and parsed withjson(). - In Svelte, fetch can be used directly inside components for retrieving and posting data.
- Forms can be submitted with fetch by collecting input values using FormData.