A Page That Calls the API
Part of the REST APIs section of Coddy's Node.js journey. Lesson 21 of 25.
A page calls your API with fetch. A POST needs three options: method, headers and body. Convert the JavaScript object to JSON text for the body, and label that text as application/json.
const response = await fetch('/api/books', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({title: title}),
});
const data = await response.json();The first await receives the HTTP response. The second reads its JSON body. response.ok tells you whether its status is in the successful range. A status such as 400 or 409 does not reject the fetch promise; it gives a response whose ok is false. The form and list code are supplied; focus on sending the request and handling its result.
The supplied message variable refers to the page’s message paragraph. Set its textContent to display text, or to an empty string to clear it:
message.textContent = data.error.message;
// Clear it after success:
message.textContent = '';The page and API share an origin, so this call needs no CORS permission. FormData encodes a form differently from JSON; use JSON text because this API uses express.json().
Challenge
EasyYour API has no screen yet. Give it a small page, served by the same server, whose form adds tasks through the API.
- In
server.js, serve thepublicfolder withexpress.static, soGET /returnspublic/index.html. - In
public/index.html, the submit listener already reads the title. Make it send the new task to the API:- Use the supplied
titlevariable containing the input text. - Send it with
fetch('/api/tasks', ...)as a POST. - The body is JSON text made with
JSON.stringify, like{"title":"Water the plants"}. - The request needs the header
'Content-Type': 'application/json', infetch'sheadersoption, orexpress.json()will not read the body.
- Use the supplied
- If the response is OK (its
okproperty is true for any status from 200 to 299), clear the form withform.reset(), empty#message, and callload()so the list shows the new task. - Otherwise the response body is the error shape from earlier, for example:Show its
{ "error": { "code": "conflict", "message": "A task with this title already exists" } }messagein the#messageparagraph.
The checks execute this supplied page script with a small simulated form and the real lesson API. They submit a task and a duplicate, then inspect the list, form and message. Also try the actual page beside the editor.
Try it: send GET /. The page opens in the page view with the 3 starting tasks. Type "Water the plants" and press Add: the input empties and the task appears at the bottom of the list. Type "Water the plants" again and press Add: the list stays the same, and "A task with this title already exists" appears under the form.
Try it yourself
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tasks</title>
</head>
<body>
<h1>Tasks</h1>
<ul id="list"></ul>
<form id="add">
<input name="title" placeholder="New task" required>
<button>Add</button>
</form>
<p id="message"></p>
<script>
const list = document.querySelector('#list');
const form = document.querySelector('#add');
const message = document.querySelector('#message');
async function load() {
const response = await fetch('/api/tasks?limit=50');
const page = await response.json();
list.replaceChildren(...page.items.map((task) => {
const item = document.createElement('li');
item.textContent = (task.done ? '[x] ' : '[ ] ') + task.title;
return item;
}));
}
form.addEventListener('submit', async (event) => {
event.preventDefault();
const title = form.elements.title.value;
// Send the title to POST /api/tasks as JSON. On success clear
// the form and load() again; on an error show its message.
});
load();
</script>
</body>
</html>
All lessons in REST APIs
1Resources and Verbs
Resources and URLsCreating with POST4Browsers, Versions and Config
What Is an OriginAllowing Another OriginCORSA Page That Calls the APIPractice on your own: Express playground