Hello! Welcome to the final lesson in our module on Asynchronous JavaScript.
Introduction
Throughout this module, we've explored the core concepts of handling asynchronous operations. You've learned how fetch works, how async/await makes your code cleaner, how to handle errors with try/catch, and how to run multiple requests concurrently with Promise.all().
Today, we bring all of these pieces together. Our goal is to build a simple app to fetch data from a public API and render it on a page. This lesson is a mini-project that transitions you from understanding individual concepts to applying them in a practical, tangible wayâa key step toward your goal of building full-stack applications.
The Application Workflow
Building a client-side application that communicates with an API follows a standard workflow. Understanding these steps is crucial:
- Setup (HTML): Create the basic user interface structure in an HTML file. This includes placeholders where your data will be displayed (like
divs,imgtags, or lists) and elements for user interaction (likeinputfields andbuttons). - Fetch (JavaScript): Write an
asyncfunction to make afetchrequest to the API endpoint when a user performs an action (like clicking a button) or when the page loads. - Error Handling (JavaScript): Wrap your fetch logic in a
try/catchblock. Inside thetryblock, check the response status (e.g.,response.ok) to ensure the request was successful before proceeding. - Parse & Process (JavaScript): If the request is successful, use
response.json()to parse the data into a usable JavaScript object. - Render (JavaScript): Use DOM manipulation methods (
getElementById,textContent,src,createElement,appendChild, etc.) to inject the processed data into the HTML placeholders you created in Step 1.
This fetch-and-render cycle is the foundation of almost every modern web application.

Project: The PokÊmon Finder
Let's build a small application that allows a user to type in a PokÊmon's name, click a button, and see an image of that PokÊmon fetched from the free and public PokÊAPI.
This project directly implements the workflow described above and will be a great exercise to solidify your skills.
First, create two files in a new folder: index.html and app.js.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PokÊmon Finder</title>
<style>
body { font-family: sans-serif; text-align: center; margin-top: 50px; }
img { width: 150px; height: 150px; display: none; margin: 20px auto; }
p { color: red; }
</style>
</head>
<body>
<h1>PokÊmon Finder</h1>
<input type="text" id="pokemonName" placeholder="Enter PokÊmon name">
<button id="fetchButton">Fetch PokÊmon</button>
<img id="pokemonSprite" src="" alt="PokÊmon Sprite">
<p id="error" style="display: none;"></p>
<script src="app.js"></script>
</body>
</html>
app.js
We will now write the logic for app.js. The following video provides a complete, step-by-step walkthrough of this exact project. It's a perfect real-time demonstration of the concepts we've covered.
How to FETCH data from an API using JavaScript âŠī¸
This video from Bro Code will guide you through building the PokÊmon finder. It starts by refactoring a .then() based fetch to use async/await and then builds the full interactive application.
Watch from 06:09 to the end (13:46). The first part (until 08:56) shows how to structure the async function with try/catch and error checking. The second part (from 08:56) shows how to connect this function to the HTML elements to build the complete app. Try to code along in your app.js file!
After following the video, your app.js should look something like this. Let's break down how it maps to our workflow:
// Get references to our HTML elements
const fetchButton = document.getElementById('fetchButton');
const pokemonNameInput = document.getElementById('pokemonName');
const pokemonSpriteImg = document.getElementById('pokemonSprite');
const errorP = document.getElementById('error');
// Add a click event listener to the button
fetchButton.addEventListener('click', fetchData);
async function fetchData() {
try {
// Step 2: Fetch
const pokemonName = pokemonNameInput.value.toLowerCase();
const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonName}`);
// Step 3: Error Handling
if (!response.ok) {
throw new Error("Could not fetch resource. Is the name correct?");
}
// Step 4: Parse
const data = await response.json();
const pokemonSpriteUrl = data.sprites.front_default;
// Step 5: Render
pokemonSpriteImg.src = pokemonSpriteUrl;
pokemonSpriteImg.style.display = "block";
errorP.style.display = "none"; // Hide any previous error message
} catch (error) {
// Also part of Error Handling and Rendering
console.error(error);
errorP.textContent = error.message;
errorP.style.display = "block";
pokemonSpriteImg.style.display = "none"; // Hide the image on error
}
}
Notice how try is used for the "happy path" (fetch, parse, render success) and catch handles the "unhappy path" (rendering an error message). This is a very robust and common pattern.
Alternative Rendering: Displaying a List of Data
Our PokÊmon app fetches and displays a single item. But what if your API returns an array of items? In this case, you need to iterate over the array and create an HTML element for each item.
As a Laravel developer, this is analogous to looping through a collection in a Blade template to render a table or list, but here we're doing it on the client-side with JavaScript.
The following tutorial demonstrates this pattern by fetching a list of dog facts and creating a new paragraph element for each one.
How to Use the JavaScript Fetch API to Get Data from the NASA APOD API
This tutorial from Sophia Li shows another example of fetching and rendering. While it uses the NASA API, the DOM manipulation technique is universal.
Read the section Display the Data on our Browser. Focus on the displayData function. See how it uses document.getElementById() to select elements and then updates their .textContent and .src properties with the data received from the API.
Here's how you might adapt that concept to display a list. Imagine you fetched an array of products from your e-commerce backend: [{name: 'Shirt', price: 20}, {name: 'Pants', price: 50}].
You would render it like this:
const productListUl = document.getElementById('product-list');
// Clear any existing items
productListUl.innerHTML = '';
products.forEach(product => {
// 1. Create a new element
const listItem = document.createElement('li');
// 2. Set its content
listItem.textContent = `${product.name} - $${product.price}`;
// 3. Append it to the parent in the DOM
productListUl.appendChild(listItem);
});
This forEach -> createElement -> appendChild loop is the fundamental pattern for rendering lists with vanilla JavaScript.
Conclusion
Congratulations on completing the Asynchronous JavaScript module! You have successfully built a small but complete application that interacts with a real-world API.
Key Takeaways:
- You can build a client-side app by following a clear workflow: Setup -> Fetch -> Error Handle -> Parse -> Render.
async/awaitandtry/catchprovide a robust structure for managing API requests and their potential failures.- DOM manipulation methods like
getElementById,textContent,createElement, andappendChildare the tools you use to make your fetched data appear on the page. - You can render both single data items (like our PokÊmon) and lists of data (by looping and creating elements).
Preview of Next Lesson:
In this lesson, we wrote code to manually find elements and update the DOM. While effective for simple cases, this can become complex and error-prone in large applications.
This is where a library like React comes in. In our next module, we will begin our journey into React. You will learn how it provides a more declarative and efficient way to build user interfaces that automatically "react" to changes in your data, eliminating much of the manual DOM manipulation we did today. Our first step will be to describe the roles of Node.js, npm, and Vite in a modern React development environment.