IndexedDB

What is IndexedDB?

IndexedDB stands for Indexed Database, is a web standard for storing large amounts client-side data in a structured manner. This low-level API is able to index data which enables performance rich search on data.

Why IndexedDb?

Before IndexedDb, there was another storage specification called Web SQL. The W3C announced it is going to be deprecated and IndexedDb should be used as the alternative.

IndexedDb come with the following features:

  • Asynchronous API
  • Stores key-value pairs
  • Not SQL
  • Non-relational
  • Index based search API
  • Same domain data access
Why not cookies?

Cookies can support only a limited space and not ideal for storing fairly large values. Every time a request is sent, the cookies need to be sent back and forth as well.

How about Local Storage?

Provides more storage than cookies, but still limited. It also doesn’t have a proper search API as data is stored as key value pairs.

Getting Ready

Before we start using IndexedDb feature, we need to check if the browser supports IndexedDb. We can simply do this with the following code:

var idbSupported = false;

document.addEventListener("DOMContentLoaded", function(){

  window.indexedDB = window.indexedDB || window.mozIndexedDB ||
    window.webkitIndexedDB || window.msIndexedDB;

  if (!window.indexedDB) {
    idbSupported = true;
    console.info('Your browser does not support IndexedDB.');
  } else {
    console.info('IndexedDB is supported');
  }

}, false);

The code snippet above checks if the browser you are using supports IndexedDb, and we do this check on the DOMContentLoaded event which gets fired when the document has finished loading.

Opening an IndexedDB Database

IndexedDB databases are local to the browser which is only available to the user. and the database is unique for the domain it was loaded from.

The basic usage for opening a database is you provide the name and importantly the version.

if(idbSupported) {
  var db = indexedDB.open('vehicles', 1);
}

We make sure IndexedDB is supported, if so we open the database named vehicle.

In IndexedDB, opening a database operation is asynchronous. To handle the result of this kind of operations we need to write event handlers. There are four types of events that can be fired.

  • success
  • error
  • upgradeneeded
  • blocked

Let’s incorporate some of these event handlers to our code.

if(idbSupported) {
  var db = indexedDB.open('vehicles', 1);

  openRequest.onupgradeneeded = function(event) {
      console.log("Upgrading IndexedDB");
  }

  openRequest.onsuccess = function(e) {
      console.log("Success!");
      db = e.target.result;
  }

  openRequest.onerror = function(e) {
      console.log("Error");
      console.dir(e);
  }
}

This will not do anything yet, because we don’t have the vehicles database yet. Let’s create one,

Adding Data

Before we start, let’s create some dummy data.

var vehicles = [
  { id: '01', make: 'BMW', brand: 'X5', doors: 5 },
  { id: '02', make: 'Audi', brand: 'A5', doors: 5 }
];

Next let’s create a function for adding data to the database.

function add(store, name, entry, index) {
   var transaction = store.transaction([name], 'readwrite');
   var objectStore = transaction.objectStore(name);
   var request = objectStore.add(entry, index);

   request.onsuccess = function(event) {
      console.log('%s has been added to IndexedDB', name);
   };

   request.onerror = function(event) {
      console.log('Unable to add %s\r\nIt already exists in IndexedDB!');
   }
}

Now we will update the onsuccess method to insert data to the database.

openRequest.onsuccess = function(event) {
    console.log("Success!");

    var store = event.target.result;

    var vehicles = [
      { id: '01', make: 'BMW', brand: 'X5', doors: 5 },
      { id: '02', make: 'Audi', brand: 'A5', doors: 5 }
    ];

    vehicles.forEach(function(vehicle, index) {
      add(store, 'vehicles', vehicle, index);
    });
}

Open the index.html file on your browser and then the developer tools (F9 or Cmd+Alt+I). You will see the following messages in the console as well as the entries in the IndexedDB database.

IndexedDB is supported

Success!

vehicles has been added to IndexedDB

Retrieve Data

Just like adding data to IndexedDB, we can retrieve data using get() method.

function read(store, name, entry) {
   var transaction = store.transaction([name]);
   var objectStore = transaction.objectStore(name);
   var request = objectStore.get(entry);

   request.onsuccess = function(event) {
     if(request.result) {
       console.log(
         'Make: %s Brand: %s', request.result.make,
         request.result.brand);
     } else {
        console.log('Unable to find the key %s', entry);
     }
   };

   request.onerror = function(event) {
      console.log(
        'Unable to retrive %s\r\nIt already exists in IndexedDB!',
        entry
      );
   }
}

Before testing this code, if you have run the code before, make sure you clear the vehicles table in the DevTools resource tab.

Now the console output will look like the following:

IndexedDB is supported

Success!

vehicles has been added to IndexedDB

Make: BMW Brand: X5

Conclusion

IndexedDB brings basic database capability to the browser, making it possible to build web applications that work online and off. It does, however, require shifting your mind a bit, and becoming familiar with database concepts.

You can find the source code for this article in Github.

Be first to comment

Leave a Reply