DEV Community

Akash for MechCloud Academy

Posted on

2

Your Browser's Backpack: Fetching and Storing Data

Welcome back to our journey into the browser's hidden superpowers! So far, we've learned why Web APIs are essential (Part 1) and how to manipulate the page with the DOM API (Part 2). Our applications are now interactive, but they have a problem: they have no memory and can't talk to the outside world.

Today, we're giving our browser a backpack. This backpack has two pockets:

  1. A walkie-talkie to communicate with servers anywhere on the internet. This is the Fetch API.
  2. A notebook to jot down information and remember it later. This is the Web Storage API.

Mastering these two APIs will elevate your vanilla JavaScript projects from simple toys to full-fledged applications.

Your Walkie-Talkie: The Fetch API

For years, developers used a clunky tool called XMLHttpRequest (often nicknamed "XHR") to make network requests. It was powerful but had a complicated and unintuitive syntax.

The Fetch API is its modern, powerful, and much cleaner replacement. It's based on Promises, which makes handling asynchronous operations (like waiting for a server to respond) a breeze.

Making a GET Request (Fetching Data)

Let's fetch some user data from the free JSONPlaceholder API, just like we previewed in Part 1.

The async/await syntax is the cleanest way to work with Promises. Let's break down the process.

// A function to fetch and display users
async function fetchUsers() {
  const userList = document.querySelector('#user-list');

  try {
    // 1. "await" the response from the server
    const response = await fetch('https://jsonplaceholder.typicode.com/users');

    // 2. Check if the response was successful (status 200-299)
    if (!response.ok) {
      // If not, throw an error to be caught by the catch block
      throw new Error(`Network response was not ok: ${response.statusText}`);
    }

    // 3. The response body is a stream. We need to parse it as JSON.
    // This is also an asynchronous operation, so we "await" it.
    const users = await response.json();

    // 4. Now we have the data! We can use our DOM skills from Part 2.
    users.forEach(user => {
      const li = document.createElement('li');
      li.textContent = user.name;
      userList.append(li);
    });

  } catch (error) {
    // If anything goes wrong in the try block, it gets caught here.
    console.error('Fetch error:', error);
    userList.textContent = 'Failed to load users.';
  }
}

// Call the function
fetchUsers();
Enter fullscreen mode Exit fullscreen mode

That's it! In a few lines of readable code, we've made a network request, handled potential errors, parsed the data, and updated the DOM. No libraries needed.

Making a POST Request (Sending Data)

What about sending data to a server? Fetch handles this elegantly too. We just need to pass a second argument: an options object.

async function createUser(userData) {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'POST', // Specify the HTTP method
      headers: {
        // Tell the server we're sending JSON
        'Content-Type': 'application/json'
      },
      // The data we're sending, converted to a JSON string
      body: JSON.stringify(userData)
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const result = await response.json();
    console.log('Successfully created user:', result);

  } catch (error) {
    console.error('Error creating user:', error);
  }
}

// Example usage:
const newUser = {
  name: 'Jane Doe',
  username: 'janedoe99',
  email: 'jane@example.com'
};

createUser(newUser);
Enter fullscreen mode Exit fullscreen mode

Your Notebook: The Web Storage API

Okay, we can fetch data. But what if the user refreshes the page? Our beautiful list of users disappears. We need a way to store information in the browser itself.

The Web Storage API provides a simple, persistent key-value store. It comes in two flavors.

1. localStorage

Think of localStorage as a permanent notebook. Data saved here persists even after the browser is closed and reopened. It's perfect for saving user settings (like a "dark mode" preference) or a JWT token for authentication.

The API is incredibly simple:

  • localStorage.setItem('key', 'value'): Save a value.
  • localStorage.getItem('key'): Retrieve a value.
  • localStorage.removeItem('key'): Delete a value.
  • localStorage.clear(): Delete everything.

Important: localStorage can only store strings. If you want to store a JavaScript object, you must convert it to a string with JSON.stringify() first, and parse it back with JSON.parse() when you retrieve it.

Example: Saving a theme preference.

const themeToggleButton = document.querySelector('#theme-toggle');

// On page load, check if a theme is saved in localStorage
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
  document.body.classList.add(savedTheme);
}

themeToggleButton.addEventListener('click', () => {
  document.body.classList.toggle('dark-mode');

  // After toggling, save the current state
  if (document.body.classList.contains('dark-mode')) {
    localStorage.setItem('theme', 'dark-mode');
  } else {
    localStorage.removeItem('theme'); // Or set it to 'light-mode'
  }
});
Enter fullscreen mode Exit fullscreen mode

2. sessionStorage

sessionStorage is like a sticky note for the current browser tab. It has the exact same API as localStorage (setItem, getItem, etc.), but with one key difference: the data is cleared when the tab is closed.

It's perfect for storing temporary information that shouldn't stick around forever, like data for a multi-page form or the state of a shopping cart before checkout.

A Glimpse into the Future: IndexedDB

For simple key-value pairs, localStorage is perfect. But what if you need to store large amounts of structured data and query it efficiently, like a real database? For that, the browser provides IndexedDB. It’s a full-fledged, transactional, client-side database. It’s significantly more complex than localStorage, but it's the right tool for building powerful offline-first applications. We won't cover it in detail here, but it's the next logical step in your data storage journey.

What's Next?

Our application is getting smart. It can control the page (DOM), talk to servers (Fetch), and remember things (Web Storage). It's starting to feel like a real app.

But we can push it further. We can make it interact with the user's physical world.

In Part 4, we'll bridge the digital-physical divide by exploring Device APIs. We'll get the user's location, pop up system notifications, and interact with their clipboard!

A Layered Approach to Mobile App Protection

A Layered Approach to Mobile App Protection

Attackers use static analysis to understand how your app functions and the data it contains. By using multiple layers of protections like code obfuscation and string encryption, you can prevent attackers from accessing your app.

Read more

Top comments (0)

Developer-first embedded dashboards

Developer-first embedded dashboards

Embed in minutes, load in milliseconds, extend infinitely. Import any chart, connect to any database, embed anywhere. Scale elegantly, monitor effortlessly, CI/CD & version control.

Get early access

👋 Kindness is contagious

Explore this practical breakdown on DEV’s open platform, where developers from every background come together to push boundaries. No matter your experience, your viewpoint enriches the conversation.

Dropping a simple “thank you” or question in the comments goes a long way in supporting authors—your feedback helps ideas evolve.

At DEV, shared discovery drives progress and builds lasting bonds. If this post resonated, a quick nod of appreciation can make all the difference.

Okay