JavaScript Foundations • StreetGeek Academy

🧠 MODULE 9: Fetch API, Async/Await & Local Storage

Learn how to connect your website to external data sources using the Fetch API, handle asynchronous code with async/await,
and store/retrieve data locally using the browser’s Storage APIs.

1) What Is the Fetch API?

The Fetch API lets you make network requests (like loading data from an API) using a simple syntax.
Think of it as: “Go get this data → wait for it → then show it on the page.”

Basic Example

fetch("https://api.github.com/users/SitesByYogi")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error("Error:", error));
✅ This retrieves data from GitHub and logs it in your console.

2) Using Async/Await (Modern Syntax)

Instead of chaining .then() calls, you can write cleaner, synchronous-style code using
async/await.

async function getUser() {
  try {
    const response = await fetch("https://api.github.com/users/SitesByYogi");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Error fetching data:", error);
  }
}

getUser();
💡 await pauses until the Promise resolves — only usable inside an async function.

3) Displaying API Data on Your Portfolio

Let’s fetch your latest GitHub repos and show them on your Projects page.

HTML

<section id="github-projects">
  <h2>Latest GitHub Projects</h2>
  <ul id="repo-list"></ul>
</section>

JavaScript

async function loadRepos() {
  const repoList = document.getElementById("repo-list");
  try {
    const response = await fetch("https://api.github.com/users/SitesByYogi/repos");
    const repos = await response.json();

    repoList.innerHTML = ""; // clear existing list

    repos.slice(0, 5).forEach(repo => {
      const li = document.createElement("li");
      li.innerHTML = `<a href="${repo.html_url}" target="_blank">${repo.name}</a>`;
      repoList.appendChild(li);
    });
  } catch (error) {
    repoList.innerHTML = "<li>⚠️ Unable to load projects.</li>";
  }
}

loadRepos();
✅ Dynamically displays your 5 most recent repositories from GitHub.

4) Local Storage — Saving Data in the Browser

localStorage is like a tiny database built into your browser.
It stores key-value pairs that persist even after refreshing or closing the browser.

Example

localStorage.setItem("theme", "dark"); // Save data

const theme = localStorage.getItem("theme"); // Retrieve data
console.log(theme); // "dark"

Remove or Clear

localStorage.removeItem("theme");
localStorage.clear(); // deletes all items

5) Example: Remember Dark Mode Preference

HTML

<button id="theme-toggle">🌙 Toggle Theme</button>

JavaScript

const toggleBtn = document.getElementById("theme-toggle");
const body = document.body;

// Apply saved theme on load
if (localStorage.getItem("theme") === "dark") {
  body.classList.add("dark");
}

// Toggle and save theme
toggleBtn.addEventListener("click", () => {
  body.classList.toggle("dark");
  const mode = body.classList.contains("dark") ? "dark" : "light";
  localStorage.setItem("theme", mode);
});
✅ The browser remembers your theme preference — even after you reload.

6) Session Storage (Temporary Storage)

Similar to localStorage, but data is erased when the tab closes.

sessionStorage.setItem("sessionUser", "Yogi");
console.log(sessionStorage.getItem("sessionUser"));
💡 Use it for temporary session data, not long-term preferences.

7) Fetching and Rendering JSON Data (Local File)

You can also load a local .json file instead of an API.

data/projects.json

[
  { "title": "Portfolio",  "tech": "HTML/CSS/JS" },
  { "title": "ShopBlocks", "tech": "PHP/WooCommerce" }
]

JavaScript

async function loadLocalProjects() {
  const response = await fetch("data/projects.json");
  const data = await response.json();
  console.table(data);
}

loadLocalProjects();
✅ Perfect for practice or offline environments.

8) Handling Loading & Error States

Users shouldn’t see a blank section — show loading and fallback messages.

const repoList = document.getElementById("repo-list");
repoList.innerHTML = "<li>⏳ Loading projects...</li>";

try {
  const response = await fetch("https://api.github.com/users/SitesByYogi/repos");
  const repos = await response.json();
  // render data...
} catch (err) {
  repoList.innerHTML = "<li>❌ Failed to fetch data.</li>";
}
✅ Always handle all states: loading → success → error.

9) Combining Fetch + Storage (Practical)

Cache data locally to avoid re-fetching every time.

async function getRepos() {
  const cached = localStorage.getItem("repos");

  if (cached) {
    console.log("Loaded from cache");
    return JSON.parse(cached);
  }

  console.log("Fetching from API...");
  const response = await fetch("https://api.github.com/users/SitesByYogi/repos");
  const data = await response.json();
  localStorage.setItem("repos", JSON.stringify(data));
  return data;
}

getRepos().then(data => console.log(data));
✅ Combines API performance + persistence.

10) Quiz Time

Show/Hide Questions

1) What does the Fetch API do?

2) What’s the difference between .then() and async/await?

3) What’s the difference between localStorage and sessionStorage?

4) What’s the best way to handle API errors gracefully?

5) How do you convert a JSON response into a JavaScript object?

🚀 Challenge Task — Live Data + Preferences Integration

Enhance your Portfolio Projects section with:

  • A “Load Projects” button that fetches from your GitHub automatically.
  • A loading spinner or text while fetching.
  • A theme toggle that saves the user’s choice in localStorage.
  • A “Last Updated” timestamp stored and retrieved from localStorage.

Bonus: Store fetched repos for 24 hours

const now = Date.now();

localStorage.setItem("repos", JSON.stringify({
  time: now,
  data: repos
}));

const cached = JSON.parse(localStorage.getItem("repos"));

if (cached && now - cached.time < 86400000) { // 24 hours in ms
  renderRepos(cached.data);
}
✅ You now have a real, data-connected, state-aware portfolio site — just like professional web apps.

🏁 Module 9 Summary

  • How to use the Fetch API to load external or local data
  • How to handle async code with async/await
  • How to save and retrieve data using localStorage
  • How to handle API errors and loading states gracefully
  • How to combine live data with stored preferences

Next up → MODULE 10: Final Project — Interactive Portfolio v2.0
You’ll integrate everything you’ve learned — DOM manipulation, events, fetch, storage — into one cohesive interactive experience.