Skip to content

Instantly share code, notes, and snippets.

@andrewluetgers
Last active August 29, 2015 14:13
Show Gist options
  • Save andrewluetgers/9bf09e447993e7786ce5 to your computer and use it in GitHub Desktop.
Save andrewluetgers/9bf09e447993e7786ce5 to your computer and use it in GitHub Desktop.
DynaCache: Speed up angular $http requests with Localforage response cache
angular.module("dynacache", [])
.service("dynacache", function($http) {
// drop in replacement for $http
// currently supports "get", "post", "put", "jsonp" methods
// caches response body in localforage (http://mozilla.github.io/localForage/)
// subsequent requests immediately serve up local data
// whilst fetching new data from the server
// once ajax returns, new data replaces old by firing success handler once again
// expects lodash _ global to be present
function config() {
localforage.config({
name : 'clario',
version : 1.0,
storeName : 'cache_' + clairoUser.id
});
}
config();
function clear(fn) {
localforage.config();
localforage.clear(fn);
}
function keys(fn) {
localforage.config();
localforage.keys(fn);
}
function _idFromConfig(config) {
return (config.method || "get").toLowerCase() + ":" + config.url + "?" + (decodeURIComponent($.param(config.params)) || "" );
}
var _$dcMethods = {
success: function (fn) {
var that = this;
var pending = "";
this.endSuccess = function () {
console.log("success", that);
var hit = that.hit;
if (that.req) {
console.log("with req");
// fetched from server
var id = _idFromConfig(that.config);
pending = id;
that.req.success(function (data, status, headers, config) {
// save it locally
console.log("saving", id);
localforage.setItem(id, {
data: data,
status: status
}, function (err, val) {
if (err) {
console.log(err);
}
console.log("saved", id, {
data: data,
status: status
});
if (id == pending) {
$rootScope.$apply(function () {
fn(data, status, headers, config);
});
}
});
});
}
if (hit) {
// pull value from the cache
console.log("with hit", _idFromConfig(that.config), hit.data);
$rootScope.$apply(function() {
fn(hit.data, hit.status, hit.headers, hit.config);
});
}
};
return this;
},
error: function (fn) {
var that = this;
this.endError = function () {
console.log("error", that);
if (that.req) {
// fetched from server
that.req.error(function (data, status, headers, config) {
$rootScope.$apply(function () {
fn(data, status, headers, config);
});
});
}
};
return this;
}
};
function _$dc(config, fetchFn) {
var ret = _.extend({
req: null,
hit: null,
config: config
}, _$dcMethods);
localforage.getItem(_idFromConfig(config), function(err, val) {
ret.req = fetchFn(config);
ret.hit = val || false;
console.log("got item", _idFromConfig(config), err, val);
if (ret.endError) { ret.endError(); }
if (ret.endSuccess) { ret.endSuccess(); }
});
console.log("ret", _idFromConfig(config), ret);
return ret;
}
// support $http() and $http.method()
var methods = ["get", "post", "put", "jsonp"];
function dynaCache(config) {
return _$dc(config, $http);
}
dynaCache.success = _$dcMethods.success;
dynaCache.error = _$dcMethods.error;
dynaCache.idFromConfig = _idFromConfig;
dynaCache.keys = keys;
dynaCache.clear = clear;
_.each(methods, function(method) {
dynaCache[method] = function(url, opts) {
var config = _.create(opts || {}, {url: url, method: method});
return _$dc(config, $http);
};
});
return dynaCache;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment