Hi! Let's look now at some pieces of code and examples that will explain how to really program an IndexedDB application.
So… one of the first thing is that you need to create or to open an existing database before working with data.
All operations are asynchronous and, if you want to open a database, you use IndexedDB.open(…).
You specify the name of the database and the version.
Each database is versioned... and if the "CustomerDB" database -from this example- exists with a version "2", it will just open it.
If it exists, but with a previous, lower version, it will be "upgraded".
This is why we need to define, on the object that is returned by open(...), some event listeners.
The "onsuccess" listener is called when the database has been opened. "onerror" (listener) if there is an error, and "onupgradeneeded" (listener) will be called only if we are creating a new version of the database.
It's the case when the database does not exist.
So the database has a version, and the first version is "0".
You can have the same database that exists in different versions at a time, but the very common way is to define the two listeners I talked about, and create the database and the schema in the "onupgradeneeded" event listener.
And work with data on the "onsuccess" listener… because when you enter in the "onsuccess », it means that the database exists.
Be careful because on the Web you will find lots and lots of old tutorials that use a previous, deprecated version of the API.
You can identify that if it uses the setVersion() method on an object called IDBDatabase.
In that case look for a more recent tutorial!
Here is an example of a database creation: you indicate a name... "customerDB", you try to open it with version "2", and if the database does not exist, you will enter the "onupgradeneeded" listener.
If it exists, you go to the "onsuccess" listener.
The result (the event.target.result) will be the database itself.
We will work with this object for inserting, deleting, modifying or looking for data.
Now, let's zoom a little bit on what happens in this listener here, because this is where we are going to create the database.
For creating and populating a new object datastore - a new object database -, here is how we proceed: in the "onupgradeneeded" listener, we get the database itself...
Then you create an object store in it, and you need to indicate the name of the object store - "customers" - and the name of the "KeyPath".
Remember, the KeyPath is a unique ID that will be attached to all objects stored in the database (!: correction ➡ datastore).
And we can also create "indexes".
Here, we are saying that every object that will be stored in the database (!: correction ➡ datastore), will have a property called "name", that will not be necessarily unique, and we will have a property called "email" that will be unique.
Just after creating it, we are populating the objectstore with some test data.
Here we are iterating on the customerData object, that has been defined here.
It's an array, that contains two persons (two customers) inside: one is "Bill", age 35, with an email and a unique ID that is its social security number.
Let's try this one: it comes from the example called "creating and deleting a database".
I open it, I open the devtools, and I look at "Resources" (tab).
I open the "IndexedDB" (item).
You can see that the datastore and the database are not present here.
I click on the "create customer database" … this will run the code I just explained.
And if I refresh the IndexedDB, I can see that the database called "CustomerDB" has been created, with inside an object store called "customers", that contains two persons (two customers), and I can see here the indexes.
I can open also the objects.
If I want to delete the database, I can do it in my own program, or I can do it in the console.
I run IndexedDB.deleteDatabase(...), and I indicate the database - "customerDB" - .
If I go back to the "Resources" tab, and refresh the databases, heu.. if I refresh IndexedDB (databases) -sorry-... normally, ok I run it again... normally, it disappears... sometimes the refresh does not work correctly, but the database is really deleted.
Our online example at JSBin shows how to create and populate an object store named "CustomerDB". This example should work on both mobile and desktop versions of all major post-2012 browsers.
We suggest that you follow what is happening using Google Chrome's developer tools. Other browsers offer equivalent means for debugging Web applications that use IndexedDB.
With Chrome, please open the JSBin example and activate the Developer tool console (F12 or cmd-alt-i). Open the JavaScript and HTML tabs on JSBin.
Then, click the "Create CustomerDB" button in the HTML user interface of the example: it will call the createDB() JavaScript function that:
creates a new IndexedDB database and an object store in it ("customersDB"), and
inserts two javascript objects (look at the console in your devtools - the Web app prints lots of traces in there, explaining what it does under the hood). Note that the social security number is the "Primary key", called a key path in the IndexedDB vocabulary (red arrow on the right of the screenshot).
Chrome DevTools (F12 or cmd-alt-i) shows the IndexedDB databases, object stores and data:
Normally, when you create a database for the first time, the console should show this message:
This message comes from the JavaScript request.onupgradeneeded callback. Indeed, the first time we open the database we ask for a specific version (in this example: version 2) with:
var request = indexedDB.open(dbName, 2);
...and if there is no version "2" of the database, then we enter the onupgradeneeded callback where we actually create the database.
You can try to click again on the button "CreateCustomerDatabase", if database version "2" exists, this time the request.onsuccess callback will be called. This is where we will add/remove/search data (you should see a message on the console).
Notice that the version number cannot be a float: "1.2" and "1.4" will automatically be rounded to "1".
JavaScript code from the example:
var db; // the database connection we need to initialize
function createDatabase() {
if(!window.indexedDB) {
window.alert("Your browser does not support a stable version
of IndexedDB");
}
// This is what our customer data looks like.
var customerData = [
{ ssn: "444-44-4444", name: "Bill", age: 35, email:
"bill@company.com" },
{ ssn: "555-55-5555", name: "Donna", age: 32, email:
"donna@home.org" }
];
var dbName = "CustomerDB";
// version must be an integer, not 1.1, 1.2 etc...
var request = indexedDB.open(dbName, 2);
request.onerror = function(event) {
// Handle errors.
console.log("request.onerror errcode=" + event.target.error.name);
};
request.onupgradeneeded = function(event) {
console.log("request.onupgradeneeded, we are creating a
new version of the dataBase");
db = event.target.result;
// Create an objectStore to hold information about our
// customers. We're going to use "ssn" as our key path because
// it's guaranteed to be unique
var objectStore = db.createObjectStore("customers",
{ keyPath: "ssn" });
// Create an index to search customers by name. We may have
// duplicates so we can't use a unique index.
objectStore.createIndex("name", "name", { unique: false });
// Create an index to search customers by email. We want to
// ensure that no two customers have the same email, so use a
// unique index.
objectStore.createIndex("email", "email", { unique: true });
// Store values in the newly created objectStore.
for (var i in customerData) {
objectStore.add(customerData[i]);
}
}; // end of request.onupgradeneeded
request.onsuccess = function(event) {
// Handle errors.
console.log("request.onsuccess, database opened, now we can add
/ remove / look for data in it!");
// The result is the database itself
db = event.target.result;
};
} // end of function createDatabase
All the "creation" process is done in the onupgradeneeded callback (lines 26-50):
Line 30: get the database created in the result of the dom event: db = event.target.result;
Line 35: create an object store named "customers" with the primary key being the social security number ("ssn" property of the JavaScript objects we want to store in the object store): var objectStore = db.createObjectStore("customers", {keyPath: "ssn"});
Lines 39 and 44: create indexes on the "name" and "email" properties of JavaScript objects: objectStore.createIndex("name", "name", {unique: false});
Lines 48-50: populate the database: objectStore.add(...).
If we try to open a database version that exists, then the request.onsuccess callback is called. This is where we are going to work with data. The DOM event result attribute is the database itself, so it is wise to store it in a variable for later use: db= event.target.result;
You can delete a database simply by running this command:
indexedDB.deleteDatabase("databaseName");
A common practice, while learning how IndexedDB works, is to type this command in the devtool console. For example, we can delete the CustomerDB database used in all examples of this course section by opening one of the JsBin examples , then opening the devtool console, then executing indexedDB.deleteDatabase("CustomerDB"); in the console: