So I have this JS indexedDB library:
window.db = {
name:"indexedDBname",
varsion:0.7,
_settings:"indexedDBobject",
h:null, // Handler to the db
open:function(callback,callback1) {
var r = indexedDB.open( db.name );
r.onupgradeneeded = function(e){ console.log(".onupgradeneeded is not yet supported by webkit"); };
r.onsuccess = function(e){
db.h = e.target.result;
if( db.version !== db.h.version ) {
var v = db.h.setVersion( db.version );
v.onsuccess = function(e) {
if(db.h.objectStoreNames.contains( db._settings )) db.h.deleteObjectStore( db._settings );
db.h.createObjectStore(db._settings, { keyPath:"name" });
};
v.onfailure = db.onerror;
v.onerror = db.onerror;
v.onblocked = db.onerror;
}
// CALLBACKS
if(typeof callback=="function" && typeof callback1=="function") callback.call(window,callback1);
else if(typeof callback=="function" && typeof callback1!="function") callback.call(window);
};
r.onfailure = db.onerror;
},
getSettings:function(callback){ // retrieve user custom settings
var t = db.h.transaction( [db._settings], IDBTransaction.READ_ONLY ),
s = t.objectStore(db._settings),
keyRange = IDBKeyRange.lowerBound(0),
cursorRequest = s.openCursor(keyRange),
tmp = {};
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if(!!result==false) {
// CALLBACKS
if(typeof callback=="function") callback.call(window);
return;
}
tmp[result.value.name] = result.value.value;
result.continue();
}
cursorRequest.onerror = db.onerror;
},
onerror:function(e){ console.log("Handle and print error here:"+e); }
};
// actual run
db.open( db.getSettings, user.applySettings);
Which I tend to use pretty often, but as you can see, those callback doesn't look too well... And when I want to do series of tasks or even call any of those functions with set of their own parameters, my code starts to look really choppy, ex.
db.open('forWhichUser',newSettingsToApplyObject, callback1, argumentForCallback1, secondOptionalArgument, callback2, etc);
So in the old days I'll just do:
db.open('userName', settingsMap);
var opts = db.getSettings();
user.downloadInfoBasedOn( opts );
user.renderInfoTo('userDataHolderId');
but now, since everything can start/finish in unpredictable moments (depending on computer performance, db size, etc, etc...) how do I handle all of that asynchronicity keeping code graceful and readable?
You can use the JavaScript promises/deferreds pattern:
Promises/deferreds can help you create a much easier and readable async code. You can use jQuery deffered object to achieve that (http://api.jquery.com/category/deferred-object/)
Another option is to use story.js which wrap the IndexedDB API and exposes it in a much simpler way (http://blogs.microsoft.co.il/blogs/gilf/archive/2012/04/21/the-story-begins.aspx)
I hope you will find this answer helpful.
Gil