UNPKG

10.9 kBMarkdownView Raw
1Cached Resource
2===============
3
4An [AngularJS][angular] module to interact with RESTful server-side data
5sources, even when the browser is offline. Uses HTML5
6[localStorage][localStorage] under the hood. Closely mimics the behavior of
7the core [ngResource][ngResource] module, which it requires as a dependency.
8
9[![Build Status][travis-badge]][travis-link]
10
11## Features
12
13* Provides a simple abstraction to retrieve and save objects from a RESTful
14 server.
15* Comes with a set of intelligent defaults that let you get started right away.
16* Caches all requests, and returns them immediately from the cache if you
17 request them again.
18* Remmebers writes to the server, and adds them to the cache too.
19* If a write fails, try it again periodically until it succeeds. (This even
20 works if you refresh the page in between!)
21* If you query for multiple resources in one request, each one is cached
22 separately so you can request it from the cache individually, too.
23* Works as a drop-in replacement for [Angular's $resource][ngResource] module.
24
25## News
26
27It looks like this sort of functionality might be built into the upcoming Angular 2.0.
28[Check out the design document here](https://docs.google.com/document/d/1DMacL7iwjSMPP0ytZfugpU4v0PWUK0BT6lhyaVEmlBQ/edit#).
29
30----
31
32## A simple example
33
34```javascript
35
36// Register your module with ngCachedResource
37angular.module('myApp', ['ngCachedResource']);
38
39// Define a resource
40var Article = $cachedResource('article', '/articles/:id', {id: "@id"});
41
42// GET requests:
43var a1 = Article.get({id: 1});
44a1.$promise.then(function() {
45 console.log('From cache:', a1);
46});
47a1.$httpPromise.then(function() {
48 console.log('From server:', a1);
49});
50
51// POST/PUT/PATCH/DELETE requests:
52var a2 = new Article({id: 2});
53a2.title = "This article will be saved eventually...";
54a2.body = "Even if the browser is offline right now.";
55a2.$save();
56a2.$promise.then(function() {
57 console.log('Article was successfully saved.');
58});
59```
60
61Read the [tutorial on the Bites from Good Eggs
62blog](http://bites.goodeggs.com/open_source/angular-cached-resource/).
63
64-------
65
66## Installing
67
68**Bower:**
69
70```bash
71bower install angular-cached-resource
72```
73
74**npm:** (intended for use with [browserify](http://browserify.org/))
75
76```bash
77npm install angular-cached-resource
78```
79
80**Manual Download:**
81
82- development: [angular-cached-resource.js](https://raw.githubusercontent.com/goodeggs/angular-cached-resource/master/angular-cached-resource.js)
83- production: [angular-cached-resource.min.js](https://raw.githubusercontent.com/goodeggs/angular-cached-resource/master/angular-cached-resource.min.js)
84
85---
86## Usage
87Provides a factory called `$cachedResource`:
88
89```js
90$cachedResource(cacheKey, url, [paramDefaults], [actions]);
91```
92
93### Arguments
94
95- **cacheKey**, `String`<br>
96 An arbitrary key that will uniquely represent this resource in localStorage.
97 When the resource is instanciated, it will check localStorage for any
98
99- **url**, `String`<br>
100 Exactly matches the API for the `url` param of the [$resource][ngResource]
101 factory.
102
103- **paramDefaults**, `Object`, _(optional)_<br>
104 Exactly matches the API for the `paramDefaults` param of the
105 [$resource][ngResource] factory.
106
107- **actions**, `Object`, _optional_<br>
108 Mostly matches the API for the `actions` param of the
109 [$resource][ngResource] factory. Takes an additonal `cache` param (Boolean,
110 default `true`) that determines if this action uses caching.
111
112### Returns
113
114A CachedResource "class" object. This is a swap-in replacement for an object
115created by the `$resource` factory, with the following additional properties:
116
117- **Resource.$clearCache(** [options] **)**<br>
118 Clears all items from the cache associated with this resource. Accepts one
119 argument, described below.
120
121 - **options**, `Object`, *optional*<br>
122 `options` may contain the following keys:
123 - `where`, which will limit the resources that are cleared from the cache
124 to only those whose keys are explicitly listed. `where` can be an `Array`
125 or an `Object`. If it is an `Object`, it will be treated like an `Array`
126 containing only the provided `Object`. The `Array` should contain `Objects`
127 representing cache keys that should be removed. If `where` is provided,
128 `exceptFor` must not be provided.
129 - `exceptFor`, which will limit the resources that are cleared from the
130 cache to all resources except for those whose keys are explicitly listed.
131 Just like `where`, `exceptFor` can be an `Array` or an `Object`. If it is an
132 `Object`, it will be treated like an `Array` containing only the provided
133 `Object`. The `Array` should contain `Object`s representing cache keys that
134 should be kept. If `exceptFor` is provided, `where` must not be provided.
135 - `isArray`, a boolean. Default is `false`. If `true`, then the function will
136 treat the `where` or `exceptFor` arguments as referring to `Array` cache key.
137 - `clearChildren`, a boolean. Default is `false`. If `true`, and `isArray` is
138 also `true`, then the function will clear the `Array` cache entry (or entries)
139 as well as all of the instances that the `Array` points to.
140 - `clearPendingWrites`, a boolean. Default is `false`. If `true`, then
141 the function will also remove cached instances that have a pending
142 write to the server.
143
144
145In addition, the following properties exist on CachedResource "instance" objects:
146
147- **resource.$promise**<br>
148 For GET requests, if anything was already in the cache, this
149 promise is immediately resolved (still asynchronously!) even as the HTTP request
150 continues. Otherwise, this promise is resolved when the HTTP request responds.
151
152- **resource.$httpPromise**<br>
153 For all requests, this promise is resolved as soon as the
154 corresponding HTTP request responds.
155
156### Clearing the cache
157
158Since there is a 5 megabyte limit on localStorage in most browsers, you'll
159probably want to actively manage the resource instances that are stored. By
160default, this module never removes cache entries, so you'll have to do this by
161hand. Here are the ways that you can accomplish this:
162
163- **[localStorage.clear()][localStorageClear]**<br>
164 Removes everything in localStorage. This will not break the behavior of
165 this module, except that it will prevent any pending write from actually
166 occurring.
167
168- **$cachedResource.clearCache()**<br>
169 Removes every single Angular Cached Resource cache entry that's currently
170 stored in localStorage. It will leave all cache entries that were not created
171 by this module. (Note: cache entries are namespaced, so if you add anything
172 to localStorage with a key that begins with `cachedResource://`, it will get
173 deleted by this call). It will also leave any resource instances that have a
174 pending write to the server.
175
176- **$cachedResource.clearUndefined()**<br>
177 Removes every Angular Cached Resource cache entry corresponding to a resource
178 that has not been defined since the page was loaded. This is useful if your
179 API changes and you want to make sure that old entries are cleared away.
180
181- **$cachedResource.clearCache({exceptFor: ['foo', 'bar']})**<br>
182 Removes every Angular Cached Resource entry except for resources with the
183 `foo` or `bar` keys, or resource instances that have a pending write to the
184 server.
185
186- **$cachedResource.clearCache({clearPendingWrites: true})**<br>
187 Removes every Angular Cached Resource entry, including those that have a
188 pending write to the server.
189
190If you have a "class" object that you've created with `$cachedResource`, then
191you can also do the following:
192
193- **CachedResource.$clearCache()**<br>
194 Removes all entries from the cache associated with this particular resource
195 class, except for resource instances that have a pending write to the server.
196
197- **CachedResource.$clearCache({where: [{id: 1}, {id: 2}])**<br>
198 Removes two entries from the cache associated with this particular resource
199 class; the ones with an `id` of 1 and 2. (This assumes that `paramDefaults`
200 has an `id` param.)
201
202- **CachedResource.$clearCache({exceptFor: {id: 1})**<br>
203 Removes all entries from the cache associated with this particular resource
204 class, except for those with an `id` of 1. (This assumes that
205 `paramDefaults` has an `id` param.)
206
207- **CachedResource.$clearCache({exceptFor: {query: 'search string'}, isArray: true})**<br>
208 Removes all entries from the cache except those that were returned by the
209 provided query parameters.
210
211- **CachedResource.$clearCache({clearPendingWrites: true})**<br>
212 Removes all instances of CachedResource from the cache, including those that
213 have a pending write to the server.
214
215------
216
217## Details
218
219**Asking for a cached resource with `get` or `query` will do the following:**
220
2211. If the request has not been made previously, it will immediately return a
222 `resource` object, just like usual. The request will go through to the
223 server, and when the server responds, the resource will be saved in a
224 localStorage cache.
225
2262. If the request has already been made, it will immediately return a
227 `resource` object that is pre-populated from the cache. The request will
228 still attempt to go through to the server, and if the server responds, the
229 cache entry will be updated.
230
231**Updating a CachedResource object will do the following:**
232
2331. Add the resource update action to a queue.
2342. Immediately attempt to flush the queue by sending all the network requests
235 in the queue.
2363. If a queued network request succeeds, remove it from the queue and resolve
237 the promises on the associated resources (only if the queue entry was made
238 after the page was loaded)
2394. If the queue contains requests, attempt to flush it once per minute OR
240 whenever the browser sends a [navigator.onOnline][onOnline] event.
241
242**What if localStorage doesn't exist, or if the browser is out of space?**
243
244In either of these cases, `$cachedResource` will make sure all of your requests
245still happen. Things end up working just like the `$resource` module, with
246none of the caching benefits.
247
248------
249
250## Development
251
252Please make sure you run the tests, and add to them unless it's a trivial
253change. Here is how you can run the tests:
254
255```
256npm install
257npm test
258```
259
260------
261
262## License
263
264[MIT](https://github.com/goodeggs/angular-cached-resource/blob/master/LICENSE.md)
265
266[travis-badge]: https://travis-ci.org/goodeggs/angular-cached-resource.svg?branch=master
267[travis-link]: https://travis-ci.org/goodeggs/angular-cached-resource
268
269[angular]: http://angularjs.org/
270[ngResource]: http://docs.angularjs.org/api/ngResource/service/$resource
271[localStorage]: http://www.w3.org/TR/webstorage/#the-localstorage-attribute
272[localStorageClear]: http://www.w3.org/TR/webstorage/#dom-storage-clear
273[onOnline]: https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine.onLine