goodeggs / angular-cached-resource

An AngularJS module to interact with RESTful resources, even when browser is offline
MIT License
216 stars 29 forks source link

Cached Resource

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.

Build Status npm version mit license

Features

News

It looks like this sort of functionality might be built into the upcoming Angular 2.0. Check out the design document here.


A simple example


// 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 ids), 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.


Installing

Bower:

bower install angular-cached-resource

npm: (intended for use with browserify)

npm install angular-cached-resource

Manual Download:


Usage

Provides a factory called $cachedResource:

$cachedResource(cacheKey, url, [paramDefaults], [actions]);

Arguments

Returns

A CachedResource "class" object. This is a swap-in replacement for an object created by the $resource factory, with the following additional properties:

In addition, the following properties exist on CachedResource "instance" objects:

Clearing the cache

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:

If you have a "class" object that you've created with $cachedResource, then you can also do the following:


Details

Asking for a cached resource with get or query will do the following:

  1. 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.

  2. 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:

  1. Add the resource update action to a queue.
  2. Immediately attempt to flush the queue by sending all the network requests in the queue.
  3. If a queued network request succeeds, remove it from the queue and resolve the promises on the associated resources (only if the queue entry was made after the page was loaded)
  4. If the queue contains requests, attempt to flush it once per minute OR whenever the browser sends a navigator.onOnline event.

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.


Development

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

License

MIT