DEV Community

Soft Heart Engineer
Soft Heart Engineer

Posted on

How to use IndexedDB? Guide on complete CRUD Operations

A Comprehensive Guide to IndexedDB: The Browser's Powerhouse for Client-Side Storage

As web applications become more sophisticated, the need for efficient client-side storage solutions has grown. IndexedDB, a low-level API for storing large amounts of structured data, is a powerful tool for web developers, software engineers, and web enthusiasts looking to create robust and offline-capable applications.

In this blog, we'll explore what IndexedDB is, how it works, and how to use it effectively with practical examples. Whether you're building a Progressive Web App (PWA), a complex dashboard, or a game, IndexedDB can help you manage data seamlessly.


What is IndexedDB?

IndexedDB is a browser-based NoSQL database designed for storing large amounts of structured data, including files and blobs. Unlike cookies or localStorage, IndexedDB allows you to store data in a structured format and query it using indexes, making it ideal for complex use cases.

Key Features of IndexedDB:

  • Asynchronous Operations: Interactions with IndexedDB are non-blocking, ensuring smooth performance.
  • Structured Data Storage: Stores data in key-value pairs, enabling efficient querying with indexes.
  • Offline Capability: Data is stored locally, making it accessible without an internet connection.
  • Large Storage Limit: Offers more storage capacity compared to cookies or localStorage.

Use Cases for IndexedDB:

  • Progressive Web Apps: Store offline data for seamless experiences.
  • Large Data Storage: Save large datasets, such as user preferences or application state.
  • Caching: Cache API responses for improved performance.

Getting Started with IndexedDB

How Does IndexedDB Work?

IndexedDB operates on a database structure consisting of:

  • Databases: Top-level containers for data.
  • Object Stores: Tables where data is stored, each identified by a unique name.
  • Indexes: Structures that optimize querying within object stores.

IndexedDB API: Basic Operations

The main operations in IndexedDB include:

  1. Opening a Database: Creating or accessing a database.
  2. Creating Object Stores: Defining storage for your data.
  3. Performing CRUD Operations: Adding, reading, updating, and deleting data.
  4. Using Transactions: Managing data operations atomically.

Example 1: Creating and Opening a Database

Here's how to create an IndexedDB database called MyDatabase with an object store users.

const dbName = "MyDatabase";
const dbVersion = 1; // Versioning is required for schema updates.

const request = indexedDB.open(dbName, dbVersion);

request.onupgradeneeded = function (event) {
  const db = event.target.result;

  // Create an object store named 'users' with 'id' as the keyPath
  if (!db.objectStoreNames.contains("users")) {
    db.createObjectStore("users", { keyPath: "id" });
  }
  console.log("Database setup complete");
};

request.onsuccess = function (event) {
  const db = event.target.result;
  console.log("Database opened successfully");
};

request.onerror = function (event) {
  console.error("Error opening database:", event.target.errorCode);
};
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • The indexedDB.open method opens or creates the database.

  • The onupgradeneeded event is triggered when creating a new database or upgrading its version.

  • An object store named users is created with id as the primary key.


Example 2: Adding Data to the Object Store

You can add data to an object store using a transaction.

function addUser(id, name, email) {
  const request = indexedDB.open("MyDatabase", 1);

  request.onsuccess = function (event) {
    const db = event.target.result;
    const transaction = db.transaction("users", "readwrite");
    const objectStore = transaction.objectStore("users");

    const user = { id, name, email };
    const addRequest = objectStore.add(user);

    addRequest.onsuccess = function () {
      console.log("User added:", user);
    };

    addRequest.onerror = function (event) {
      console.error("Error adding user:", event.target.errorCode);
    };
  };
}

// Add a new user
addUser(1, "John Doe", "john.doe@example.com");
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • A transaction is created with the readwrite mode to modify data.

  • The add method inserts data into the users object store.


Example 3: Reading Data from the Object Store

Retrieve data by using the get method or iterate over all entries.

function getUser(id) {
  const request = indexedDB.open("MyDatabase", 1);

  request.onsuccess = function (event) {
    const db = event.target.result;
    const transaction = db.transaction("users", "readonly");
    const objectStore = transaction.objectStore("users");

    const getRequest = objectStore.get(id);

    getRequest.onsuccess = function () {
      if (getRequest.result) {
        console.log("User found:", getRequest.result);
      } else {
        console.log("User not found");
      }
    };

    getRequest.onerror = function (event) {
      console.error("Error retrieving user:", event.target.errorCode);
    };
  };
}

// Get user with ID 1
getUser(1);
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • The get method fetches a specific record by its key.

  • Data retrieval is asynchronous, so success and error handlers are used.


Example 4: Updating Data in IndexedDB

Update existing records using the put method.

function updateUser(id, updatedData) {
  const request = indexedDB.open("MyDatabase", 1);

  request.onsuccess = function (event) {
    const db = event.target.result;
    const transaction = db.transaction("users", "readwrite");
    const objectStore = transaction.objectStore("users");

    const putRequest = objectStore.put({ ...updatedData, id });

    putRequest.onsuccess = function () {
      console.log("User updated:", { ...updatedData, id });
    };

    putRequest.onerror = function (event) {
      console.error("Error updating user:", event.target.errorCode);
    };
  };
}

// Update user with ID 1
updateUser(1, { name: "Johnathan Doe", email: "johnathan.doe@example.com" });
Enter fullscreen mode Exit fullscreen mode

Example 5: Deleting Data in IndexedDB

Remove a record using the delete method.

function deleteUser(id) {
  const request = indexedDB.open("MyDatabase", 1);

  request.onsuccess = function (event) {
    const db = event.target.result;
    const transaction = db.transaction("users", "readwrite");
    const objectStore = transaction.objectStore("users");

    const deleteRequest = objectStore.delete(id);

    deleteRequest.onsuccess = function () {
      console.log("User deleted with ID:", id);
    };

    deleteRequest.onerror = function (event) {
      console.error("Error deleting user:", event.target.errorCode);
    };
  };
}

// Delete user with ID 1
deleteUser(1);
Enter fullscreen mode Exit fullscreen mode

IndexedDB vs Other Storage Solutions

Feature IndexedDB localStorage sessionStorage
Storage Limit Several MB to GB 5 MB (approx) 5 MB (approx)
Data Format Key-value pairs Key-value pairs Key-value pairs
Asynchronous Yes No No
Structured Data Yes No No

Best Practices for Using IndexedDB

  • Use Transactions Properly: Always manage data operations within transactions to ensure atomicity.

  • Handle Errors Gracefully: Implement error handlers for better debugging and user feedback.

  • Version Control: Increment the database version carefully to manage schema changes.

  • Test Offline Scenarios: IndexedDB is often used for offline capabilities; ensure it functions as expected without an internet connection.


Conclusion

IndexedDB is a powerful tool for client-side data storage, offering features that far surpass traditional storage methods like localStorage. With support for structured data, large storage capacity, and offline functionality, IndexedDB is an essential technology for building modern web applications.

Key Takeaways:

  • IndexedDB is ideal for storing large and complex datasets locally.

  • Transactions are central to managing data operations in IndexedDB.

  • It provides robust offline support, making it a cornerstone of Progressive Web Apps.

By mastering IndexedDB, you can build scalable, offline-first applications with superior performance and user experience. Start experimenting with IndexedDB in your projects today!

Top comments (0)