Taming IndexedDB [1/3]
After I had quit my job and started to learn JavaScript, Progressive Web Apps aka PWA was the thing in my mind (along with some artificial intelligence and machine learning fancy stuff, of course). Switching from LAMP to MEVN was not that hard, but it took time! I thought it was better to step into the PWA only after learning the basics well.
All of it changed suddenly, once I got enrolled into Google Udacity Challenge Scholarship in Mobile Web Specialist track. I was skeptical about the encounter, but trust me, taming IndexedBD is not that hard. Let me tell you how.
IndexedDB is a transactional database embedded in the browser. The database is organized around the concept of collections of JSON objects similarly to NoSQL databases such as MongoDB. Each object is identified with a key generated during insert. An indexing system optimizes access to stored objects.
That’s pretty much it. Take a look at the following before the deep dive.
5 things to remember
Database
Highest level of IndexedDB. You can create multiple databases, but generally there is one database per app. We store everything in here.
Object Stores
Consider them as tables or collections in databases. Imagine an app which stores movie information for users, there might be 2 stores — one for user and other for movies. Unlike tables in traditional databases, the actual JavaScript data types of data within the store do not need to be consistent.
Index
It is a kinda object store for organizing data for another object store. For example, if you’re storing users, you may want to fetch them later by their name or favorite movies.
Operations and Transactions
You might be wondering why I’m trying to put these together. Because I said 5 things to remember, god dammit!! And I don’t have a gif that favors six. Let me continue. Operations are, well.. operations.. or.. interactions to the DB.
A transaction is wrapper around an operation, or group of operations, for database integrity. All read or write operations in IndexedDB must be part of a transaction. And, if one of then fail, none of them will get applied.
Cursor
Used to iterate through multiple records in database.
Finally, it’s time to get hands dirty!
Using Jake Archibald’s IndexedDB Promised API, which is built around IndexedDB with promises. Got really small footprint and enables to write elegant code compared to spaghetti making tendency of native API.
From now on, I will be using the examples from Google Codelabs mostly. They spend their time to make some good examples, and I respect that. So, it makes sense!
However, I’m gonna explain it from my perspective. In fact, planning to shrink things up a bit, to be frank. You may think I’m super lazy, but trust me. That’s all it takes to master it. Fair enough, right?
It is essential to check browser support for IDB before opening the database using idb.open
(function() {
'use strict';
//check for support
if (!('indexedDB' in window)) {
console.log('This browser doesn\'t support IndexedDB');
return;
}
var dbPromise = idb.open('test-db1', 1);
})();
Create an Object Store
Let’s create an object store. createObjectStore
is used for the same. Pretty straight forward, isn’t it? But it is essential to check that object stores exists already, before creating it.
(function() {
'use strict';
//check for support
if (!('indexedDB' in window)) {
console.log('This browser doesn\'t support IndexedDB');
return;
}
var dbPromise = idb.open('test-db2', 1, function(upgradeDb) {
console.log('making a new object store');
if (!upgradeDb.objectStoreNames.contains('firstOS')) {
upgradeDb.createObjectStore('firstOS');
}
});
})();
There are some options can be added while object creation, such as defining primary key. KeyPath
stands for unique key, and it is possible to use it with or without autoIncrement
upgradeDb.createObjectStore('logs', {keyPath: 'id', autoIncrement:true});
Remember what I told about Indexes
It is a kinda object store for organizing data for another object store. For example, if you’re storing users, you may want to fetch them later by their name or favorite movies.
Let’s make some.
(function() {
'use strict';
//check for support
if (!('indexedDB' in window)) {
console.log('This browser doesn\'t support IndexedDB');
return;
}
var dbPromise = idb.open('test-db4', 1, function(upgradeDb) {
if (!upgradeDb.objectStoreNames.contains('people')) {
var peopleOS = upgradeDb.createObjectStore('people', {keyPath: 'email'});
peopleOS.createIndex('gender', 'gender', {unique: false});
peopleOS.createIndex('ssn', 'ssn', {unique: true});
}
if (!upgradeDb.objectStoreNames.contains('notes')) {
var notesOS = upgradeDb.createObjectStore('notes', {autoIncrement: true});
notesOS.createIndex('title', 'title', {unique: false});
}
if (!upgradeDb.objectStoreNames.contains('logs')) {
var logsOS = upgradeDb.createObjectStore('logs', {keyPath: 'id',
autoIncrement: true});
}
});
})();
Mastering IDB is not for weak-minded, but prophecy says you are the chosen one! Stay tuned for part 2 to play with some data!
Update : Taming IndexedDB Part 2