There are 3 major types of storage is browsers up to date:
- IndexedDB. The future.
- localStorage. Limited in size and can be observed through the
storage
event. - WebSQL. Dropped by the W3C but it's still very present in the wild, with notable platforms like iOS and PhoneGap.
Green: IndexedDB; blue: WebSQL; yellow: localStorage
In the mobile world local cache and storage is very important for various reasons:
- faster loading times
- unreliable connections
- offline use
My particular use case is an app to be used "in the field" where you probably don't have a connection and you need to do data entry. My solution is to save to a local storage and sync to the server when a connection is available. The 5 MB of localStorage may not be enough in my case, but I won't be able to tell until the app is used by real users.
- Is there enough interest in this considering the availability of
localStorage
? - Is it too early to use these technologies?
The goal is to use conditional loading to load one of 3 or 4 sub-modules: indexeddb, websql, localstorage and a fallback to memory.
- IndexedDB uses a key-based storage organized in "object stores".
- WebSQL uses SQL tables. WebSQL can be used as a fallback for object stores by matching a table to a store and using tables with two columns: a
key
and avalue
column which saves the object serialized as JSON. - IndexedDB uses structured cloning which is similar to
JSON.parse(JSON.stringify(obj))
.
- Is falling back to localStorage a good idea considering the limited size and observability?
- Is the whole concept OK or is it too hackish?
- Should this include over-the-wire databases via some protocol?
The API aims to find the lowest common denominator between all implementations. A database requires:
- A
name
. Required by both IndexedDB and WebSQL - A
version
. Required by both IndexedDB and WebSQL - A structure, which means the name of each object store, tied to the version. Required by both IndexedDB and WebSQL
- A
size
in bytes. Required by WebSQL
A Storage
constructor receives all these parameters and creates an instance with properties with the names of each object store:
var storage = new Y.Storage({
name: 'my database',
version: 1,
size: 5242880,
stores: ['fooStore', 'barStore']
});
Assert.isObject(storage.fooStore); // true
Assert.isObject(storage.barStore); // true
A Storage
instance also has a close
method that closes the database connection/session.
A Store
object is created for each requested store in a property of the same name. A store can perform the following actions:
get
. Retrieve an object by keyput
. Insert or update an object by keyremove
. Remove an object by keyclear
. Remove all objects from the storecount
. Count the objects in the store
All methods return a promise.
Example:
storage.fooStore.put('some key', { foo: 'bar' }).then(...);
- Should
Storage
inherit fromBase
in order to use attributes for configuration and maybe fireclose
orerror
events? Aversionchange
event is very important.
Juan, I really like this!
Actually I need it (sort of) for a case of my own and started to create my own store, which doesn't come near to your approach.
Concerning your questions:
Just some notes to consider:
Regards,
Marco.