Created
February 1, 2011 19:28
-
-
Save donabrams/806462 to your computer and use it in GitHub Desktop.
Simple js caching with queuing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// This is a cache implemenation | |
// You can synchronously put(), contains() and markAsLoading(). | |
// You can asynchronously get() and getput() and putget(). | |
// | |
// get() is asynchronous because it might wait until a put() is called if | |
// the key is marked as loading. | |
// key is whatever you want it to be, required. | |
// callback is an optional function that takes 2 arguments: | |
// success/boolean and the value/? | |
// maxWait is optional, max wait time in ms | |
// | |
// putget() and getput() act both a get and a put. If the key is ready or | |
// markedAsLoading, it acts just like get(). Otherwise, it marks the key | |
// as loading, loads a value and gets it. If loader is not a function, | |
// it calls put(key,loader) and then get(key,callback). If loader is a | |
// function, it passes loader() a callback function that takes a value, | |
// calls put(key,value) then get(key,callback). | |
// | |
var cache = function(args) { | |
this.cache={}; | |
this.ready={}; | |
this.waiters={}; | |
this.allowWaiting = true; | |
this.contains = function(key) { | |
return this.ready[key] !== undefined; | |
}; | |
this.markAsLoading = function(key) { | |
this.ready = false; | |
} | |
// key is whatever you want it to be | |
// callback takes 2 arguments: success and the object | |
// maxWait in ms, optional | |
this.get = function(key, callback, maxWait) { | |
if (callback == null) { | |
return; | |
} | |
if (this.ready[key] === undefined) { | |
callback(false); | |
} else if (this.ready[key]) { | |
callback(true, this.cache[key]); | |
} else if (this.allowWaiting) { | |
this._addWaiter(key, callback, maxWait); | |
} | |
}; | |
this.put = function(key, value) { | |
this.cache[key] = value; | |
this.ready[key] = true; | |
if (this.allowWaiting) { | |
this._resumeWaiters(key,value); | |
} | |
}; | |
this.putget = this.getput = function(key, loader, callback, maxWait) { | |
if (this.ready[key] === undefined) { | |
this.markAsLoading(key); | |
if ($.isFunction(loader)) { | |
if (maxWait) { | |
this.get(key, callback, maxWait); | |
} | |
var that = this; | |
loader(function(value) { | |
that.put(key, value); | |
if (!maxWait) { | |
that.get(key, callback); | |
} | |
}); | |
} else { | |
this.put(key, loader); | |
this.get(key, callback); | |
} | |
} else { | |
this.get(key, callback); | |
} | |
}; | |
this._addWaiter = function(key, callback, maxWait) { | |
var waits = this.waiters[key] = this.waiters[key] || []; | |
var i = waits.push(callback); | |
if (maxWait) { | |
var remove = function() { | |
if (waits[i] != null) { | |
var callback = waits[i]; | |
waits[i] = null; | |
callback(false); | |
} | |
}; | |
setTimeout(remove, maxWait); | |
} | |
}; | |
this._resumeWaiters = function(key,value) { | |
var waits = this.waiters[key]; | |
$.each(waits, function(i) { | |
var callback = waits[i]; | |
if (callback != null) { | |
waits[i] = null; | |
callback(true, value); | |
} | |
}); | |
}; | |
$.extend(true, this, args); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment