HTML 5 Indexed DB API

HTML 5 Indexed DB API: HTML 5 has a very good technology known as Indexed DB which is client-side data storage for each domain. This means the HTML5 application can work with the database without having a server. This IndexedDB was introduced by W3C to replace WebSQL.

HTML 5 Indexed DB API

Difference between IndexedDB and LocalStorage in HTML5

In case if you already know the client-side storage which is known as LocalStorage.If you are new to both the Local Storage and Indexed DB because storing data on the client-side is the same. There are two major differences between Local Storage and IndexedDB, one is storing data in string format in key-value format and another one is can store entire objects in object-store.

The Local Storage has an embedded table with two columns which are id and string format value. The IndexedDB has an engine that allows having many tables. So, the IndexedDB is best for the complex data structures. Some other differences in these API’s may affect the implementation of our applications in one way or the other. Most of the times we consider the major differences that we discussed earlier.

Some features of IndexedDB

IndexedDB allows many databases and storage for everyone. Each database has a name and version number which helps to identify them. We can upgrade the database version which changes the structure of the database.

IndexedDB is NOT SQL

This is not a feature but has to consider because to avoid misunderstanding. The Indexed DB is not an SQL DB. In IndexedDB no need to describe the structure like SQL database.

HTML5 IndexedDB API is asynchronous

This is the most important feature in Indexed DB because the request we ask for opening a database is non-blocking. Let’s see an example

Example to Open Database

request = indexedDB.open('database');
database = request.result;

Here, it is invalid because the IndexedDB cant is used like this. The correct method is mentioned below.

The correct method to Open Database in Indexed DB API 

request = indexedDB.open('database');request.onsuccess = function() {
database = request.result;// Now we can perform database operations.
}

HTML5 Indexed DB API  Usage

Let’s see the clear concepts of usage of IndexedDB

Creating the Database

At first, we have to retrieve the IndexedDB object then request for the opening database with name and version.(a version is optional). In this example, we have DB(database) with a list of products that have information like name, description, price etc.

Creating the Database Example

indexeddb.js

DATABASE_NAME = 'catalog';
DATABASE_VERSION = 1;
STORE_NAME = 'product';
var database;
var indexedDB = window.indexedDB || window.webkitIndexedDB
|| window.mozIndexedBD || window.msIndexedDB;
var request = indexedDB.open(DATABASE_NAME, DATABASE_VERSION);

To get the indexedDB object, we will arrange many fallbacks for every search engine.After requesting the database we must bind the function onupgradeneeded event which creates database or upgrade the version.
indexeddb.js

request.onupgradeneeded = function() {
console.log('Database upgrade/creation.');
database = request.result;
var catalogStore = database.createObjectStore(
STORE_NAME,
{
keyPath: 'id',
autoIncrement: 'true'
}
);
catalogStore.createIndex('by_id', 'id');
catalogStore.createIndex('by_name', 'name');
console.log('The database has been created/updated.');
}

As mentioned earlier the first thing we must do is retrieve the database which is request object retrieved from IndexedDB object. Now we have to create the store for catalog with the help of the createObjectStore method.

This first parameter is the name of the store which is mandatory but the next one is options.

  • Keypath: Keypath is the “primary key” of the storage.
  • AutoIncrement: This property is used to make keypath property increment automatically for the newly inserted objects and no need to consider to provide value.

In case if you have created a primary key you can also create an index that gives permissions to access. With the help of creating the index method, we have created both name and id parameters, the name parameter is used to retrieve the data and other parameters are the property it corresponds to. Unless you change the database version all these statements will execute.

Inserting Data

In the database we can insert data at creation time or later, you can also create inside the onupgradeneeded scope then no need to declare explicitly.

Inserting Data Example

indexeddb.js

function insertInitialData(catalogStore) {
catalogStore.put({
'name': 'A product',
'description': 'Description of a product.',
'price': 10,
});
catalogStore.put({
'name': 'Another product',
'description': 'Description of another product.',
'price': 20,
'subproduct': {
'name': 'Subproduct of a product'
}
});
}request.onupgradeneeded = function() {
// After creating the object storage and indexes...
insertInitialData(catalogStorage);// ...
}

NOTE: Here we are just inserting raw objects with properties that have not described in storage definition. In case you are using SQL then it may be quite confusing but we can insert objects without considering the properties. With the help of developer tools for the database, we can observe its data and structure.

The following image describes the database and data with chromium developer tools.

HTML5 IndexedDB APIVisualizing database data with Chromium developer tools

In case you want to insert data after the creation, we can do it onupgradeneeded scope. Another event onsuccess which is triggered after creating/updating the database successfully. Let’s see an example by inserting some values.

Insert values to Database Example

indexeddb.js

request.onsuccess = function() {
console.log('Successful request for IndexedDB.');
database = request.result;
var transaction = database.transaction(STORE_NAME, 'readwrite');
var catalogStore = transaction.objectStore(STORE_NAME);
var moreData = [
{
'name': 'A third product',
'description': 'Description of a third product.'
},
{
'name': 'Yet another product',
'description': 'One last product.'
}
];moreData.forEach(function(data) {
catalogStore.put(data);
});transaction.oncomplete = function() {
console.log('Transaction completed successfully.');
}transaction.onerror = function(error) {
console.log('An error occurred during the transaction: ' + error);
}
}

After database request, we first create a transaction for the given store which exists in the database. If you are inserting data then the transaction will provide write access bypassing read-write value as the second parameter. Here in this transaction, we get storage objects with the help of the put method we insert the data. there are handlers that specify th success, failure, transactions that define oncomplete and onerror events.

In case if you want to insert several objects in a single transaction and any one of the transition fails then rollback will happen immediately.

Retrieving Data

The basic steps to retrieve data is the same as inserting the data. at first, we have to create transaction later we get storage from it. With the storage, we can retrieve the information by making a “query” and making the request to this index.

Retrieving Data Example

indexeddb.js

function query() {
var transaction = database.transaction(STORE_NAME, 'readonly');
var catalogStore = transaction.objectStore(STORE_NAME);
var idIndex = catalogStore.index('by_id');
var nameIndex = catalogStore.index('by_name');
var request = idIndex.get(1);
request.onsuccess = function() {
console.log(request.result);
}
var request2 = nameIndex.get('Another product');
request2.onsuccess = function() {
console.log(request2.result);
}
}

Here we made different requests on different indexes to see how the indexes are working and with the help of onsuccedd event, the API is asynchronous.

Because of this reason, we created other requests in case we use the first request object we get an exception like ” The request has not finished”.The result should be like following

Object {
name: "A product",
description: "Description of a product.",
price: 10,
id: 1
}
Object {
name: "Another product",
description: "Description of another product.",
price: 20,
subproduct: Object,
id: 2
}

Cursors in IndexedDB

IndexedDB will support cursors which are very easy. The following example will show all the elements in the storage.

Cursors in IndexedDB Example

function queryWithCursor() {
var transaction = database.transaction(STORE_NAME, 'readonly');
var catalogStore =transaction.objectStore(STORE_NAME);
catalogStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
console.log(cursor.value);
cursor.continue();
}
}
}

Summary

The above example shows the usage of HTML5 IndexedDB, which is used for storing data on the client-side. At first, IndexedDB is not the option for storing data on the client-side that’s why we have compared with LocalStorage. We have a deal with IndexedAPI like creating the database, inserting data, etc.