|
1 |
| -# Ionic 2 cache service |
| 1 | +# Ionic cache service |
2 | 2 |
|
3 |
| -My Ionic 2 cache service that can cache almost everything, include requests. It's made up to use WebSQL or SQLite |
4 |
| -as storage and work well with Observables. |
| 3 | +Ionic cache service that can cache almost everything. **It caches request, observables, promises and classic data.** It uses WebSQL or SQLite |
| 4 | +as storage and work well with Observables. With few little changes it can be used separatelety in Angular 2 application. |
5 | 5 |
|
6 |
| -**It's not well tested yet, so use it at your own risk.** Please report all bugs to bug report or fix it, or |
7 |
| -better fix it and send pull request :) |
| 6 | +Key features: |
| 7 | ++ Request caching |
| 8 | ++ Delayed observable caching (see docs for more info) |
| 9 | ++ Don't invalidate cache if is browser offline |
| 10 | ++ Set and invalidate groups of entries |
| 11 | + |
| 12 | +Please report all bugs to bug report or fix it, or better fix it and send pull request :) |
| 13 | + |
| 14 | +#### Contributors |
| 15 | + |
| 16 | +Big thanks to all contributors for help. Currently only one Vojta Tranta, but I hope there will be more names in future :) |
8 | 17 |
|
9 | 18 | ## Install
|
10 | 19 |
|
11 |
| -Simple copy file to your providers folder and inject it in *app.js* file. |
| 20 | +Via NPM: |
12 | 21 |
|
13 |
| -```js |
14 |
| -import {CacheProvider} from "./providers/cache-provider/cache-provider"; |
| 22 | +```bash |
| 23 | +npm install ionic-cache --save |
| 24 | +cordova add plugin cordova-sqlite-storage --save |
| 25 | +``` |
| 26 | + |
| 27 | +And inject service to your app: |
| 28 | + |
| 29 | +```ts |
| 30 | +import {CacheService} from "ionic-cache/ionic-cache"; |
15 | 31 |
|
16 | 32 | @App({
|
17 |
| - templateUrl: "build/app.html", |
18 |
| - providers: [CacheProvider] |
| 33 | + templateUrl: "build/app.html" |
19 | 34 | })
|
20 | 35 | class MyApp {
|
21 |
| - static get parameters() { |
22 |
| - return [[IonicApp], [Platform], [CacheProvider]]; |
23 |
| - } |
24 |
| - |
25 |
| - constructor(app, platform, cache) { |
| 36 | + constructor(cache: CacheService) { |
26 | 37 | ...
|
27 | 38 | this.cache = cache;
|
28 |
| - |
29 |
| - this.cache.setTTL(60); //set default cache TTL for 1 minute |
| 39 | + this.cache.setDefaultTTL(60 * 60); //set default cache TTL for 1 hour |
30 | 40 | ....
|
31 | 41 | }
|
32 | 42 | ...
|
| 43 | +} |
| 44 | +ionicBootstrap(MyApp, [ |
| 45 | + CacheService |
| 46 | +]); |
33 | 47 | ```
|
34 | 48 |
|
35 | 49 | ## Usage
|
36 | 50 |
|
37 |
| -#### Cache request response body |
| 51 | +#### Cache request |
38 | 52 |
|
39 |
| -```js |
40 |
| -import {CacheProvider} from '../cache-provider/cache-provider'; |
| 53 | +```ts |
| 54 | +... |
| 55 | +import {CacheService} from "ionic-cache/ionic-cache"; |
41 | 56 |
|
42 | 57 | @Injectable()
|
43 |
| -export class CategoryProvider { |
44 |
| - static get parameters() { |
45 |
| - return [[Http], [CacheProvider]] |
46 |
| - } |
47 |
| - |
48 |
| - constructor(http, cache) { |
| 58 | +export class SomeProvider { |
| 59 | + constructor(http: Http, cache: CacheService) { |
49 | 60 | this.http = http;
|
50 | 61 | this.cache = cache;
|
51 | 62 | }
|
52 | 63 |
|
53 | 64 | loadList() {
|
54 |
| - let url = "http://google.com"; |
| 65 | + let url = "http://ip.jsontest.com"; |
55 | 66 | let cacheKey = url;
|
56 |
| - |
57 | 67 | let request = this.http.get(url).map(res => res.json());
|
58 |
| - return this.cache.loadItem(cacheKey, request); |
| 68 | + |
| 69 | + return this.cache.loadFromObservable(cacheKey, request); |
59 | 70 | }
|
60 | 71 | ...
|
61 | 72 | ```
|
62 | 73 |
|
63 | 74 | #### Cache whole request response
|
64 | 75 |
|
65 | 76 | Sometimes you need to cache whole response, if you need to look to Headers etc. It can be done only with simple
|
66 |
| -move *.map(res => res.json())* after *loadItem* method. *LoadItem* returns Observable, so you can also use other |
67 |
| -Observable operators |
| 77 | +move *.map(res => res.json())* after *loadFromObservable* method. *loadFromObservable* returns Observable, so you can also use other |
| 78 | +Observable operators. |
68 | 79 |
|
69 | 80 | ```js
|
70 | 81 | ...
|
71 | 82 | let request = this.http.get(url);
|
72 |
| -return this.cache.loadItem(cacheKey, request).map(res => res.json()); |
| 83 | +return this.cache.loadFromObservable(cacheKey, request).map(res => res.json()); |
| 84 | +... |
| 85 | +``` |
| 86 | +
|
| 87 | +#### Cache classic data (arrays, objects, strings, numbers etc.) |
| 88 | +
|
| 89 | +Cache service works well with observables, but you can cache classic data as well. |
| 90 | +
|
| 91 | +```js |
| 92 | +... |
| 93 | +let key = 'heavily-calculated-function'; |
| 94 | + |
| 95 | +this.cache.getItem(key).catch(() => { |
| 96 | + // fall here if item is expired or doesn't exist |
| 97 | + let result = heavilyCalculatedFunction(); |
| 98 | + return this.cache.saveItem(key, result); |
| 99 | +}).then((data) => { |
| 100 | + console.log("Saved data: ", data); |
| 101 | +}); |
| 102 | +... |
| 103 | +``` |
| 104 | +
|
| 105 | +#### Cache promises |
| 106 | +
|
| 107 | +```js |
| 108 | +... |
| 109 | +let key = 'some-promise'; |
| 110 | + |
| 111 | +this.cache.getItem(key).catch(() => { |
| 112 | + // fall here if item is expired or doesn't exist |
| 113 | + return somePromiseFunction().then(result => { |
| 114 | + return this.cache.saveItem(key, result); |
| 115 | + }); |
| 116 | +}).then((data) => { |
| 117 | + console.log("Saved data: ", data); |
| 118 | +}); |
73 | 119 | ...
|
74 | 120 | ```
|
75 | 121 |
|
76 | 122 | #### Cache with custom Observable operators
|
77 | 123 |
|
78 |
| -*LoadItem* method using Observable and return Observable, so you can use lot of Observable operators. |
79 |
| -For example error handling (on error, retry request every 6 seconds): |
| 124 | +*loadFromObservable* method using Observable and return Observable, so you are free to use all Observable operators. |
| 125 | +For example error handling (on error, retry request every 6 seconds if fails): |
80 | 126 |
|
81 | 127 | ```js
|
82 | 128 | ...
|
83 | 129 | let request = this.http.get(url)
|
84 | 130 | .retryWhen((error) => {
|
85 | 131 | return error.timer(6000);
|
86 | 132 | }).map(res => res.json());
|
87 |
| -return this.cache.loadItem(cacheKey, request); |
| 133 | +return this.cache.loadFromObservable(cacheKey, request); |
88 | 134 | ...
|
89 | 135 | ```
|
90 | 136 |
|
91 | 137 | #### Cache entries grouping
|
92 | 138 |
|
93 |
| -This is really nice feature. Sometimes you need to invalidate only some group of cache entries. |
| 139 | +Sometimes you need to invalidate only some group of cache entries. |
94 | 140 | For example if you have have long infinite scroll with lots of pages, and user trigger pull to request you want to delete
|
95 |
| -all cache entries for all pages. So this is time for third parameter groupKey. |
| 141 | +all cache entries for all pages. So this is time for third parameter. |
96 | 142 |
|
97 | 143 | ```js
|
98 | 144 | ...
|
99 | 145 | loadList(pageNumber) {
|
100 | 146 | let url = "http://google.com/?page=" + pageNumber;
|
101 | 147 | let cacheKey = url;
|
102 |
| - let groupKey = "googleListPages" |
| 148 | + let groupKey = "googleSearchPages" |
103 | 149 |
|
104 | 150 | let request = this.http.get(url).map(res => res.json());
|
105 |
| - return this.cache.loadItem(cacheKey, request, groupKey); |
| 151 | + return this.cache.loadFromObservable(cacheKey, request, groupKey); |
106 | 152 | }
|
107 | 153 | ...
|
108 | 154 | ```
|
109 | 155 |
|
110 |
| -And on pull to refresh delete all cache entries in group *googleListPages*: |
| 156 | +And when pull to refresh is fired, delete all cache entries in group *googleListPages*: |
111 | 157 |
|
112 | 158 | ```js
|
113 | 159 | ...
|
114 | 160 | pullToRefresh() {
|
115 |
| - this.cache.removeByGroup("googleListPages"); |
| 161 | + this.cache.clearGroup("googleSearchPages"); |
116 | 162 | }
|
117 | 163 | ...
|
118 | 164 | ```
|
119 | 165 |
|
120 |
| -#### Set custom TTL for single request |
| 166 | +#### Delayed observable caching |
121 | 167 |
|
122 |
| -If you want custom TTL for single request, it can by easily done by third parameter. |
| 168 | +Features that using full power of observables. When you call this method and it will return data from cache (even if they are expired) |
| 169 | +and immediately send request to server and return new data after request successfuly finish. See example for more details: |
123 | 170 |
|
124 | 171 | ```js
|
125 | 172 | ...
|
126 |
| -loadList(pageNumber) { |
127 |
| - ... |
128 |
| - let ttl = 60 * 60 * 24 * 7; // TTL in seconds for one week |
129 |
| - |
130 | 173 | let request = this.http.get(url).map(res => res.json());
|
131 |
| - return this.cache.loadItem(cacheKey, request, groupKey, ttl); |
132 |
| -} |
| 174 | + let delayType = 'all'; // send new request to server everytime, if it's set to none it will send new request only when entry is expired |
| 175 | + let response = this.cache.loadFromDelayedObservable(cacheKey, request, groupKey, ttl, delayType); |
| 176 | + |
| 177 | + response.subscribe(data => { |
| 178 | + console.log("Data:" data); |
| 179 | + }); |
| 180 | + |
| 181 | + //result will look like this: |
| 182 | + // Data: "Hello world from cache" |
| 183 | + // Data: "Hello world from server" |
133 | 184 | ...
|
134 | 185 | ```
|
135 | 186 |
|
136 |
| -#### Cache non-observables (arrays, strings etc.) |
| 187 | +#### Set custom TTL for single request |
137 | 188 |
|
138 |
| -You can cache numbers, strings, arrays, objects etc. |
| 189 | +If you want custom TTL for single request, it can by easily done by third parameter. |
139 | 190 |
|
140 | 191 | ```js
|
141 |
| -... |
142 |
| -let arrayToCache = ["Hello", "World"]; |
143 |
| -let key = 'test-array'; |
| 192 | +let ttl = 60 * 60 * 24 * 7; // TTL in seconds for one week |
| 193 | +let request = this.http.get(url).map(res => res.json()); |
144 | 194 |
|
145 |
| -this.cache.saveItem(key, arrayToCache, null, 60).then((data) => { |
146 |
| - console.log("Saved data: ", data); |
147 |
| -}); |
| 195 | +return this.cache.loadFromObservable(cacheKey, request, groupKey, ttl); |
| 196 | +``` |
148 | 197 |
|
149 |
| -this.cache.getItem(key).then((data) => { |
150 |
| - console.log('Test of load saved data: ', data); |
151 |
| -}) |
152 |
| -... |
| 198 | +#### Set default TTL |
| 199 | +
|
| 200 | +```js |
| 201 | +this.cache.setDefaultTTL(60 * 60); //set default cache TTL for 1 hour |
153 | 202 | ```
|
154 | 203 |
|
155 | 204 | #### Delete expired entries
|
156 | 205 |
|
157 | 206 | It's automatically done on every startup, but you can do it manually.
|
158 | 207 |
|
159 | 208 | ```js
|
160 |
| -this.cache.removeExpired(); |
| 209 | +this.cache.clearExpired(); |
161 | 210 | ```
|
162 | 211 |
|
163 | 212 | #### Delete all entries
|
164 | 213 |
|
165 | 214 | ```js
|
166 |
| -this.cache.removeAll(); |
167 |
| -``` |
168 |
| -
|
169 |
| -#### Set default TTL |
170 |
| -
|
171 |
| -```js |
172 |
| -this.cache.setDefaultTTL(60 * 60); //set default cache TTL for 1 hour |
| 215 | +this.cache.clearAll(); |
173 | 216 | ```
|
174 | 217 |
|
175 | 218 | #### Disable cache
|
176 | 219 |
|
177 |
| -If you are using *loadItem* method you can disable cache without any worrying, it will pass origin Observable through. |
178 |
| -Other method will return Promise reject. |
| 220 | +You can disable cache without any worrying, it will pass origin Observable through and all Promises will be rejected. |
| 221 | +Without any errors. |
179 | 222 |
|
180 | 223 | ```js
|
181 |
| -this.cache.enableCache = false; //Disable cache |
| 224 | +this.cache.disableCache(true); |
182 | 225 | ```
|
183 | 226 |
|
| 227 | +#### Disable offline invalidate |
184 | 228 |
|
| 229 | +If you want disable "don't invalidate" when device is offline, you can do it simply. |
185 | 230 |
|
186 |
| -For more inspiration look into code :) |
| 231 | +```js |
| 232 | +this.cache.setOfflineInvalidate(true); |
| 233 | +``` |
0 commit comments