Storehouse – Client Side Object Storage for the Dojo Store API

Posted by filed under Dojo Love, Goodies to go, Storage.

It’s been some time since dojox/storage, and a lot of things changed since then. Most notably: Browsers now have IndexedDB, and Dojo now has the dojo/store API that widgets can directly work with.

The dojo/store API was built with IndexedDB and offline in mind, has a nice API and allows asynchronism, meaning that it can return Promises instead of values. The only thing missing was a persistence layer that would take data via that API and store it in the user’s browser, e.g. for offline availability.

And that’s what Storehouse is: A persistent object store implementing the dojo/store API.

How it works

Storehouse is built upon dojo/store/Memory, so you have all the API you have with the Memory store, just that the data gets persisted client-side.

Behind the covers, it uses IndexedDB as storage engine and falls back to localStorage if IndexedDB is not available – if that fails, too, it uses cookies as a last resort to store the data.

Storehouse keeps a copy of the stored data in memory, allowing for fast, synchronous read access and queries.

Only write operations are asynchronous (as the underlying engine might work asynchronously itself), and return Promises to make working with it as easy as possible. For more information on Promises, please refer to the Dojo documentation.

Getting Started

Download the Storehouse package and place it somewhere in your app’s directories, e.g. next to the dojo folder.

Adding Storehouse to your app

Storehouse comes as an AMD module, so it can be easily required, but we need to tell dojo where to find it. To do so, we use the dojoConfig configuration object:

You can then require it in your app:

The Storehouse constructor takes an object as only argument that is used for configuration. In addition to the storeId property, which is used to identify the store, there is an optional idProperty property: You can use that to define which property on the objects you are going to store should be used to identify them. By default, this is set to id. However, for different types of objects, it can be useful to set this to something else. An example: If you want to store customer data, and the customer objects have a customerId property that is unique to each customer, you could use this to identify the objects:

Now, Storehouse will work with the customerId property to identify objects.

Reading/Writing Data

Before we can do data operations, we first must open the Storehouse instance. The open() call returns a Promise:

Reading data works in a synchronous fashion, just like with dojo/store/Memory. To obtain an object from the store, call the get() method and provide the object’s id as argument:

To run a query against the store, call the query() method and pass a query object argument:

For querying, Storehouse uses dojo’s simpleQueryEngine. For more details on querying, please refer to the tutorial about Dojo Object Stores.

Writing data works in an asynchronous fashion. Methods that write data are put(), add() and remove(). Those methods return a promise. Storing a data object looks like this:

Same goes for removal:

An example of CRUD operations can be found here: http://jensarps.github.io/storehouse/example/basic/.
The source code of the example can be found here: https://github.com/jensarps/storehouse/tree/master/example/basic.

Using Storehouse as data store for Widgets

Widgets that connect to the dojo/store API – i.e. widgets that have a dojo store as data backend – work with Storehouse out of the box. Just pass an opened Storehouse instance as store to the widget, just like you would do with a Memory store:

That’s it – everything that is added to the store is now persisted and available to the widget.

An example of using Storehouse as store for a ComboBox widget can be found here: http://jensarps.github.io/storehouse/example/widget/.
The source code of the example can be found here: https://github.com/jensarps/storehouse/tree/master/example/widget.

Setting Engine Preference

Storehouse has a configurable engine preference; be default, the order of preference is: IndexedDB, localStorage, Cookie. This, however can be changed. If you want Storehouse to prefer localStorage as backend over IndexedDB, you can tell it so in the constructor:

If you, e.g., want to prevent the use of Cookies at all costs, just remove 'cookie' from the list:

As you can see, the names in the enginePreference Array are all lower-case.

Links / Further Reading

Storehouse:
* Project Home and Download
* Usage Instructions and Method Overview

Examples:
* Examples to Run in the Browser
* Example Source Code

Dojo Object Stores:
* Intro to Dojo Object Store
* SitePen Blog post on Dojo Object Stores

Dojo Promises:
* Tutorial on Dojo Deferreds and Promises
* dojo/promise Documentation

[Comments are automatically closed after 30 days.]

Comment via Google+