Now for the big payoff. All of this asynchronous stuff exists mainly so that JavaScript can do one incredibly important thing: talk to other computers over the internet.
Websites constantly load data from servers: the weather, news, your messages, product lists, football scores. They usually do this through an API (Application Programming Interface): a web address that, instead of giving you a web page, gives you data, usually as JSON (Grade 8).
JavaScript's built-in tool for this is fetch. It sends a request to a URL and returns a promise for the response.
Let's try it with a free practice API called JSONPlaceholder, which provides fake data for learning. Run this in your browser console (or in a file with Node.js 18 or newer):
async function getUser() {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const user = await response.json();
console.log(user.name);
console.log(user.email);
console.log(user.address.city);
}
getUser();
Output
Leanne Graham Sincere@april.biz Gwenborough
You just loaded real data from a server somewhere on the internet! 🌍
There are two awaits here, and both matter:
await fetch(url)waits for the server to respond. It gives you aResponseobject, which is like the envelope the data comes in.await response.json()waits for the whole body of the response to arrive, and then converts it from JSON text into a JavaScript object (likeJSON.parse, but asynchronous).
Handling errors properly
Lots of things can go wrong when talking to the internet. The user's Wi-Fi might drop. The server might be down. You might have a typo in the URL. A well-behaved app handles all of these:
async function getPost(id) {
try {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
if (!response.ok) {
throw new Error(`Server said: ${response.status}`);
}
const post = await response.json();
console.log(`📰 ${post.title}`);
} catch (error) {
console.log(`😢 Couldn't load post ${id}: ${error.message}`);
}
}
getPost(2);
getPost(99999);
Output
📰 qui est esse 😢 Couldn't load post 99999: Server said: 404
This surprises everyone. fetch only rejects (throws) if the request couldn't be made at all, like when there's no internet connection. If the server responds with an error code, like 404 (Not Found) or 500 (Server Error), fetch considers that a successful response! You have to check response.ok yourself, which is true for successful status codes (200 to 299) and false otherwise. Always check it.
Showing fetched data on the page
Let's combine fetch with the DOM (Grade 11) to show a list of posts on a web page:
<h1>Latest posts</h1>
<p id="status">Loading...</p>
<ul id="posts"></ul>
async function loadPosts() {
const status = document.querySelector("#status");
const list = document.querySelector("#posts");
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts?_limit=5");
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const posts = await response.json();
posts.forEach((post) => {
const li = document.createElement("li");
li.textContent = post.title;
list.append(li);
});
status.textContent = `Loaded ${posts.length} posts.`;
} catch (error) {
status.textContent = `Sorry, something went wrong: ${error.message}`;
}
}
loadPosts();
The page first shows "Loading..." and then, a moment later, a list of five posts appears. If you turn off your Wi-Fi and refresh, you'll see the friendly error message instead of a broken page. This loading → success or error pattern is how almost every app on the internet works.
(The ?_limit=5 at the end of the URL is a query parameter: extra information for the server. This particular API uses it to decide how many posts to send back. Different APIs support different parameters, which are described in their documentation.)
If you try to fetch from some websites, you might see a red error in the console mentioning CORS (Cross-Origin Resource Sharing). For security, browsers only let a web page read data from a different website if that website says it's okay. Public APIs designed for this (like JSONPlaceholder) allow it. Many other websites don't. This isn't a bug in your code. It's the other server deciding who it will share with. (Node.js doesn't have this restriction, because it isn't a browser.)
There are thousands of free APIs out there! Some fun ones: JSONPlaceholder (fake practice data), Open-Meteo (weather forecasts, which you'll use in your Senior year), REST Countries (facts about every country), and the Official Joke API (random jokes, varying quality). Search for "public APIs list" to find many more.