An AngularJS module to interact with RESTful server-side data sources, even when the browser is offline. Uses HTML5 localStorage under the hood. Closely mimics the behavior of the core ngResource module, which it requires as a dependency.
It looks like this sort of functionality might be built into the upcoming Angular 2.0. Check out the design document here.
// Register your module with ngCachedResource
angular.module('myApp', ['ngCachedResource']);
// Define a resource
var Article = $cachedResource('article', '/articles/:id', {id: "@id"});
// GET requests:
var a1 = Article.get({id: 1});
a1.$promise.then(function() {
console.log('From cache:', a1);
});
a1.$httpPromise.then(function() {
console.log('From server:', a1);
});
// POST/PUT/PATCH/DELETE requests:
var a2 = new Article({id: 2}); // *Note: setting the bound param (`id` in this case) is *required*
a2.title = "This article will be saved eventually...";
a2.body = "Even if the browser is offline right now.";
a2.$save();
a2.$promise.then(function() {
console.log('Article was successfully saved.');
});
Read the tutorial on the Bites from Good Eggs blog.
*Note: Internally, $cachedResource keeps track of writes by bound params to ensure that it doesn't duplicate writes. If your bound param is null (say you're relying on the server to generate id
s), then every write will replace the previous one. To avoid this undesirable scenario, simply ensure the id
is set on the client, and you can safely ignore it on the server.
Bower:
bower install angular-cached-resource
npm: (intended for use with browserify)
npm install angular-cached-resource
Manual Download:
Provides a factory called $cachedResource
:
$cachedResource(cacheKey, url, [paramDefaults], [actions]);
cacheKey, String
An arbitrary key that will uniquely represent this resource in localStorage.
When the resource is instanciated, it will check localStorage for any
url, String
Exactly matches the API for the url
param of the $resource
factory.
paramDefaults, Object
, (optional)
Exactly matches the API for the paramDefaults
param of the
$resource factory.
actions, Object
, optional
Mostly matches the API for the actions
param of the
$resource factory. Takes an additonal cache
param (Boolean,
default true
) that determines if this action uses caching.
A CachedResource "class" object. This is a swap-in replacement for an object
created by the $resource
factory, with the following additional properties:
Resource.$clearCache( [options] )
Clears all items from the cache associated with this resource. Accepts one
argument, described below.
Object
, optionaloptions
may contain the following keys:
where
, which will limit the resources that are cleared from the cache
to only those whose keys are explicitly listed. where
can be an Array
or an Object
. If it is an Object
, it will be treated like an Array
containing only the provided Object
. The Array
should contain Objects
representing cache keys that should be removed. If where
is provided,
exceptFor
must not be provided.exceptFor
, which will limit the resources that are cleared from the
cache to all resources except for those whose keys are explicitly listed.
Just like where
, exceptFor
can be an Array
or an Object
. If it is an
Object
, it will be treated like an Array
containing only the provided
Object
. The Array
should contain Object
s representing cache keys that
should be kept. If exceptFor
is provided, where
must not be provided.isArray
, a boolean. Default is false
. If true
, then the function will
treat the where
or exceptFor
arguments as referring to Array
cache key.clearChildren
, a boolean. Default is false
. If true
, and isArray
is
also true
, then the function will clear the Array
cache entry (or entries)
as well as all of the instances that the Array
points to.clearPendingWrites
, a boolean. Default is false
. If true
, then
the function will also remove cached instances that have a pending
write to the server.In addition, the following properties exist on CachedResource "instance" objects:
resource.$promise
For GET requests, if anything was already in the cache, this
promise is immediately resolved (still asynchronously!) even as the HTTP request
continues. Otherwise, this promise is resolved when the HTTP request responds.
resource.$httpPromise
For all requests, this promise is resolved as soon as the
corresponding HTTP request responds.
Since there is a 5 megabyte limit on localStorage in most browsers, you'll probably want to actively manage the resource instances that are stored. By default, this module never removes cache entries, so you'll have to do this by hand. Here are the ways that you can accomplish this:
localStorage.clear()
Removes everything in localStorage. This will not break the behavior of
this module, except that it will prevent any pending write from actually
occurring.
$cachedResource.clearCache()
Removes every single Angular Cached Resource cache entry that's currently
stored in localStorage. It will leave all cache entries that were not created
by this module. (Note: cache entries are namespaced, so if you add anything
to localStorage with a key that begins with cachedResource://
, it will get
deleted by this call). It will also leave any resource instances that have a
pending write to the server.
$cachedResource.clearUndefined()
Removes every Angular Cached Resource cache entry corresponding to a resource
that has not been defined since the page was loaded. This is useful if your
API changes and you want to make sure that old entries are cleared away.
$cachedResource.clearCache({exceptFor: ['foo', 'bar']})
Removes every Angular Cached Resource entry except for resources with the
foo
or bar
keys, or resource instances that have a pending write to the
server.
$cachedResource.clearCache({clearPendingWrites: true})
Removes every Angular Cached Resource entry, including those that have a
pending write to the server.
If you have a "class" object that you've created with $cachedResource
, then
you can also do the following:
CachedResource.$clearCache()
Removes all entries from the cache associated with this particular resource
class, except for resource instances that have a pending write to the server.
CachedResource.$clearCache({where: [{id: 1}, {id: 2}])
Removes two entries from the cache associated with this particular resource
class; the ones with an id
of 1 and 2. (This assumes that paramDefaults
has an id
param.)
CachedResource.$clearCache({exceptFor: {id: 1})
Removes all entries from the cache associated with this particular resource
class, except for those with an id
of 1. (This assumes that
paramDefaults
has an id
param.)
CachedResource.$clearCache({exceptFor: {query: 'search string'}, isArray: true})
Removes all entries from the cache except those that were returned by the
provided query parameters.
CachedResource.$clearCache({clearPendingWrites: true})
Removes all instances of CachedResource from the cache, including those that
have a pending write to the server.
Asking for a cached resource with get
or query
will do the following:
If the request has not been made previously, it will immediately return a
resource
object, just like usual. The request will go through to the
server, and when the server responds, the resource will be saved in a
localStorage cache.
If the request has already been made, it will immediately return a
resource
object that is pre-populated from the cache. The request will
still attempt to go through to the server, and if the server responds, the
cache entry will be updated.
Updating a CachedResource object will do the following:
What if localStorage doesn't exist, or if the browser is out of space?
In either of these cases, $cachedResource
will make sure all of your requests
still happen. Things end up working just like the $resource
module, with
none of the caching benefits.
Please make sure you run the tests, and add to them unless it's a trivial change. Here is how you can run the tests:
npm install
npm test