HTML5 Web Storage, IndexedDB and File System

Whereas earlier courses took a quick look across a wide range of APIs, this is much more of a deep dive look at some of the most important APIs in HTML5: the persistence APIs.

This is the longest course in the learning path at 5 hours 29 minutes.

It feels like three courses in one, and if you are only interested in learning one of the three technologies (Web Storage/IndexedDB/File System), you can absolutely do this by just watching the modules associated with the particular technology you want to learn.

Having said that, until you know at least a bit about each technology, you won’t know be able to judge which technology is best suited to your needs.

I can quickly give you some very simple and basic guidance on this: if you have simple needs, use Web Storage. If you have more advanced needs, use Indexed DB. Only consider using the File System API if you don’t need to support browsers such as Microsoft Edge, Firefox and Safari.

Course Introduction

Craig begins with the relative browser support of various HTML5 APIs. These are no longer very accurate: all are better supported today (but see my review of HTML5 Advanced Topics before you use the Application Cache).

Before we get into the meat of this course, Craig gives a quick run through of how you can write modular JavaScript code. If you need to information on this, see my review of Dan Wahlin’s Structuring JavaScript Code.

I had not come across mockJSON before, but it is incredibly powerful. As Craig explains, data generation features include

In the course Craig mentions some differences between Web Storage and IndexedDB, but doesn’t give a good explanation on when you should use one over the other. For understanding this, I have found this programmer stackexchange thread very helpful.

Web Storage

Craig warns that you should cut the storage space in half, because JavaScript uses UTF16 which uses not one but two bytes per character.

Web Storage is very well supported now, but Craig points out some resources for providing fallback support.

The caveats clip is interesting, explaining how local storage works in private mode.

There are three different ways of getting and setting local storage values: using the dot operator, get/set functions, and using the bracket notation, all of which are demonstrated in the same clip. Craig likes using the dot operator, but use whichever you prefer.

There are also a couple of ways of removing data from local storage: you can either remove items on an individual basis or call clear to remove everything in one go.

For a real world example we see an input form that automatically saves the entered data to local storage.

Craig runs through a localDataService module that he wrote, which provides a nice abstraction away from some of the implementation details and makes it easier to switch to IndexDB or another storage mechanism if you wish. Also shown is how to use it inside a view model.

IndexedDB: Introduction

The Event Lifecycle begins with an Open Request, which passes the version number of the database that you want to open.

If it is a new version, the onupgradeneeded event fires, allowing you to create and remove object stores and indexes. If it is the current version, this step is skipped.

Once this work is complete, onsuccess fires, giving you the reference to the open database.

The onerror event is fired if there is an error at any point.

There are two APIs that you can use to work with IndexedDB. There’s an asynchronous API (which is like using AJAX requests), and then there is the Synchronous Web Workers API, which is covered in Craig’s Advanced Topics course.

On can I use, you can see that Safari does not support Indexed DB, however note the warning about buggy behavior. Mobile browser support is also pretty good now, however you’ll still want to listen to what Craig says about fallbacks and polyfills.

Craig makes the point that when you include Web SQL support, every modern browser now supports databases on the client.

Craig warns that the API is complex, and later covers one approach to simplify your work.

The biggest disadvantage is that it is browser-specific, so if the user spends time on your site, and then comes back later using a different browser, there’s no way to access the data that you previously stored on their browser.

IndexDB: Initialization and CRUD

This module shows you the code required to open and delete a database, create a JavaScript object that represents the database model, and do each of the CRUD operations: create, read, update, delete.

IndexDB: Cursors, Indexes and Ranges

Covers performing searches, filtering and sorting results.

Craig uses mockJSON to create 100 people objects, which are inserted into the database.

When a cursor runs, the success event fire for each object extracted from the database. There is a continue function on the cursor, which does just that.

Indexes retrieve only one object from the database (they match against the first value they find(

For doing a Select Where type of query, use Ranges. One type of Range is a bound, which is used for setting a maximum or minimum value.

There are open and closed bounds. open bounds mean the specified value is excluded from the result set

upperBound(29, true)

closed bounds include the specified value in the result set.

upperBound(29, false)

You can also do bound(10, 20) which specifies both the lower and upper bounds.

Bounds are closed by default, but you can specify that bounds are open like this:

bound(10, 20, true, true)

Finally if you are only interested in results matching one particular value, use the “only” bound:

IndexDB: Keys, Capacity, Performance and Versions

This module covers strategies for uniquely identifying data, and looks at the browser performance when large amounts of data is stored. It also covers versioning.

Craig explains the autoIncrement key (similar to identity insert in SQL, but not part of the data), and the keyPath. You can use both autoIncrement and keyPath together if you wish, and the first demo shows how to do this, as well as how to use a GUID (or UUID).

There are some situations where you will want to have one set of keys to uniquely identify objects on the client (auto incremented value, or GUID), and another set of keys to uniquely identify the objects on the server. You can then append the server key values to the objects on the client.

Working with Large Sets of Data

There is a demo with 500,000 objects in a table. The query results are pretty quick: 2 or 3 seconds to retrieve 15 to 30 thousand rows.

Managing Database Versions

In the versions clip, we see 3 different versions of the database with logic for checking the schema is correct.

Make sure the current instance of the database is closed before changing the version and opening a new instance.

Once you upgrade to a newer version of the database, you cannot access the earlier version.

Capacity Capabilities

This demo requests 58MB through AJAX and then attempts to insert it into the database. This just works in Chrome but in some browsers the user will need to give permission to go over a 50MB quota.

IndexDB: Abstractions & Implementing and Edit Screen

In this module we finally get to see a real world type of demo: a form to add homes into a database.

The whole of this module is a demonstration, which uses jQuery and Knockout to simplify some of the JavaScript, and Bootstrap for prettifying it.

Included in this module is error handling, deleting and opening a database, CRUD, and the view model code.

File System: Introduction, Concepts & Initialization

We learn that the same policies on storage quotas generally apply to all of these persistence technologies. For example you can go above 50MB in Chrome for both the File System as well as for IndexedDB.

Advice on Browser Support is still generally, and unfortunately, true, with only Chrome and Opera supporting the File System. There is good support for File API but the File System API specification is effectively dead.

Since this course was recorded, Eric has also written a popular wrapper for this API called filer, which uses Unix commands such as cp, mv and ls.

In the caveats clip, Craig warns that the File API is non transactional and callback heavy, with no search support, and with case sensitive file names. It will not work across different browsers, so your users will need to remember to return to your web application using the same browser (Chrome or Opera) as they previously used.

We also see that the user must give permission for the files to be written to their disk drive.

You can download the Chrome plugin HTML5 Filesystem Explorer (formerly known as peephole) and explore temporary and persistent memory

File System: Directories – Create, List, Delete, Move & Copy

This is a set of demonstrations showing the low level code for creating directories and sub directories, and reading them. This module also covers deletion including recursive deletion of directories and files, moving copying and renaming.

File System: Building an Abstraction Layer over Directories

This module wraps up the complexity in an abstraction layer. By the end of this module, the code that you use is much simpler and more expressive.

File System: Files – Create, Read, Write, Delete, Move & Copy

This module begins with an explanation for how to work with the files at a low level, and then builds an abstraction layer for making this work more manageable.

File System: Testing Capacity Limits & Implementing a File Editor

This module first shows that you can write out 58MB files in Chrome. It then demonstrates a file editor in the browser. Again this example uses jQuery, Knockout and Bootstrap.

Libraries

This covers three libraries:

store js is a local storage library written by Marcus Westin that provides fallback support for old browsers.

Internet Explorer 5 to 7 has a user data API. And Firefox 2+ uses Global Storage. And of course all browsers have the ability to store data in memory, which is the ultimate fallback

amplify js is another web storage library, with some features in addition to what store.js provides, such as time based expiration, an extensibility model, and abstracting AJAX requests and interfaces into UI components.
Also see Shawn Wildermuth’s introduction to Amplify in the enabling saving and wrap-up clip at the end of his Play by Play course.

lawnchair js is a JSON storage library, and is based on working with adapters, the default one being the DOM adapter which writes to local Storage. Alternative adapters include: