function Cache(loader) { this.loader = loader; this.loaded = {}; this.loading = {}; } Cache.prototype.get = function(key) { return function(f) { if(this.loaded[key] != undefined) { f(this.loaded[key]); } else { this.startLoading(key); this.loading[key].push(f); this.loader(key)(this.store(key)); } }.bind(this); }; Cache.prototype.warmUp = function(key) { if(this.loaded[key] == undefined) { this.startLoading(key); this.loader(key)(this.store(key)); } }; Cache.prototype.startLoading = function(key) { if(this.loading[key] == undefined) { this.loading[key] = []; } }; Cache.prototype.store = function(key) { return function(value) { this.loaded[key] = value; for(var i = 0; i < this.loading[key].length; i++) { this.loading[key][i](value); } this.loading[key] = null; }.bind(this); }; return { make: make }; function make(loader) { var cache = new Cache(loader); return { get: cache.get.bind(cache), warmUp: cache.warmUp.bind(cache) }; }