Using ES6 Promises to check IndexedDB store sizes

In the past JavaScript developers will almost certainly have used the Q library (or even $q in Angular), jQuery’s Deferred or Promise (which is actually just a subset of Deferred see here) or similar to provide notifications when asynchronous or deferred actions have completed.

However, the ECMAScript 6 proposal introduces native Promise objects. Hurrah!.

At the most basic level, a Promise is created as follows:

As you can see, the executor function includes two arguments; resolve and reject. These can be called once the outcome of the asynchronous operation is known. The Promise itself will be in one of four possible states:

– “pending”. The initial state of the Promise. Not rejected nor fulfilled.
– “fulfilled”. The operation relating to the Promise completed successfully.
– “rejected”. The operation relating to the Promise did NOT complete successfully.
– “settled”. The operation relating to the Promise was either fulfilled or rejected, but NOT pending.

Promises are also “thenable”, which means they expose a “then” method which gets called when the Promise is settled. The “then” function takes 2 optional as parameters which act as handlers for the outcome of the Promise. As an example:

So, lets think of a real world example where we deal with asynchronous operations………IndexedDB!!!!

Although Chrome lets us see the contents of IndexedDB, it would be nice if we could see how many bytes the database is. Heck, lets take it to the next level to see how many bytes each object store is.

Thinking of the process, we need to open the database and get the list of object stores. As you all know, you create a request to open the database which is an asynchronous operation, and when complete, the request’s “onsuccess” handler is called (or “onerror” if it goes wrong).

It would also be nice if we prompted the user to enter the database name that they want to check.

Putting it all together, we have something like:

So this function returns a Promise to us. If the request is successful, we call the Promise’s “resolve” handler and pass in the list of object stores. If the request errors, we call the Promise’s “reject” handler and pass in the error.

The next thing we need to do is think about how we will manage querying multiple object stores. For each store, we need to create another asynchronous operation to open a cursor on that store and loop round each object.

In addition to the Promise “reject” and “resolve” methods, we also have an “all” method. This method accepts an iterable list of resolvable arguments (e.g. an array of Promises).

With this in mind, we are going to create a Promise for each object store we want to query and add it to an array. We will then pass this array of Promises to the Promise.all() method once all array elements are resolved. We can then call Promise.all().then(…) to display the results.

The code to query an object store looks like this:

…and gets called once the database has been opened, pushing a new Promise into our array for each object store:

Once all Promises in PromiseArray are resolved, we display the results using the rather funky “console.table”.

That’s the principle behind Promises, but more detailed information can be found here.

The full codebase for this is available as a Chrome Snippet-friendly JavaScript on my GitHub account here.

– Jonathan