Ionic cache service that can cache almost everything.It caches requests, observables, promises and classic data.It usesIonic Storageso we support IndexedDB, SQLite (Cordova), WebSQL in this order. It can be used separatelety in Angular 2 application.
Key features:
- Request caching
- Delayed observable caching (see docs for more info)
- Don't invalidate cache if is browser offline
- Set and invalidate groups of entries
- Supports IndexedDB, SQLite (Cordova), WebSQL via Ionic Storage
Please report all bugs to bug report or fix it and send pull request:)
Via NPM:
npm install ionic-cache @ionic/storage-angular --save
or Yarn:
yarn add ionic-cache @ionic/storage-angular
You can optionally addCordova SQLite.
And inject service to your app:
app.module.ts
import{CacheModule}from"ionic-cache";
@NgModule({
...
imports:[
CacheModule.forRoot()
],
})
app ponent.ts
import{CacheService}from"ionic-cache";
@Component({
templateUrl:"build/app.html"
})
classMyApp{
constructor(cache:CacheService){
...
cache.setDefaultTTL(60*60);//set default cache TTL for 1 hour
....
}
...
}
Starting with version 3.0.2,CacheModule.forRoot()
optionally accepts a config object.
The config object currently accepts akeyPrefix
,which is the the internal key prefix to use when storing items.
For backwards compatibility this defaults to''
,but it's recommended to set this to a different value in order to prevent issues withclearAll()
.
@NgModule({
...
imports:[
CacheModule.forRoot({keyPrefix:'my-app-cache'})
],
})
...
import{CacheService}from"ionic-cache";
@Injectable()
exportclassSomeProvider{
constructor(privatehttp:HttpClient,privatecache:CacheService){}
loadList(){
leturl="http://ip.jsontest";
letcacheKey=url;
letrequest=this.http.get(url);
returnthis.cache.loadFromObservable(cacheKey,request);
}
...
If you need to cache the whole response, for example if you need to access the Headers, you can pass in an object with the observe key set to 'response', i.e.{ observe: 'response' }
.Then you can use.pipe(map(res => res.body))
to extract the response body.
...
letrequest=this.http.get(url,{observe:'response'});
returnthis.cache.loadFromObservable(cacheKey,request).pipe(map(res=>res.body));
...
loadFromObservable
accepts an Observable and returns an Observable, so you are free to use all of the Observable operators.
For example error handling (on error, retry request every 6 seconds if fails):
...
letrequest=this.http.get(url)
.pipe(retryWhen(error=>error.timer(6000)));
returnthis.cache.loadFromObservable(cacheKey,request);
...
loadFromDelayedObservable
shows off the full power of observables.
When you call this method and it will return the cached data (even if it's expired)
and immediately send a request to the server and then return the new data.
...
letrequest=this.http.get(url);
letdelayType='all';// this indicates that it should send a new request to the server every time, you can also set it to 'none' which indicates that it should only send a new request when it's expired
letresponse=this.cache.loadFromDelayedObservable(cacheKey,request,groupKey,ttl,delayType);
response.subscribe(data=>{
console.log("Data:"data);
});
//result will look like this:
// Data: "Hello world from cache"
// Data: "Hello world from server"
...
...
letkey='some-promise';
letdata=awaitthis.cache.getOrSetItem(key,()=>somePromiseFunction());
console.log("Saved data:",data);
...
Similarly, you can usegetOrSetItem
orgetItem
with classic data.
...
letkey='heavily-calculated-function';
letdata=awaitthis.cache.getOrSetItem(key,()=>heavilyCalculatedFunction());
console.log('Saved data: ',data);
...
If you need more control in the event that the item is expired or doesn't exist, you can use thegetItem
method with error handling.
...
letkey='heavily-calculated-function';
letdata=awaitthis.cache.getItem(key)
.catch(()=>{
console.log("Oh no! My promise is expired or doesn't exist!");
letresult=heavilyCalculatedFunction();
returnthis.cache.saveItem(key,result);
});
console.log('Saved data: ',data);
...
You can also remove cached items by using theremoveItem
method.
...
letkey='some-promise';
this.cache.removeItem(key);
...
You can utilize theremoveItems
method to remove multiple items based on a wildcard pattern.
...
awaitPromise.all([
service.saveItem('movies/comedy/1','Scott Pilgrim vs. The World'),
service.saveItem('movies/comedy/2','The Princess Bride'),
service.saveItem('songs/metal/1','Who Bit the Moon'),
service.saveItem('songs/metal/2','Deception - Concealing Fate, Pt. 2'),
]);
this.cache.removeItems('songs/metal/*');
...
If you need to check whether or not an item has been cached, ignoring whether or not it's expired, you can use theitemExists
method.
...
letkey='some-promise';
letexists=awaitthis.cache.itemExists(key);// returns either a boolean indicating whether it exists or not, or an error message
...
If you ever need to get a cached item regardless of whether it's expired or not, you can use thegetRawItem
method.
...
letkey='some-promise';
letitem=awaitthis.cache.getRawItem(key);
...
There's also thegetRawItems
method, which returns an array of the raw cached items.
...
letrawItems=awaitthis.cache.getRawItems();
letfirstItem=rawItems[0];//Has the properties: key, value, expires, type, groupKey
...
At times you may need to clear certain groups of cached items.
For example, if you have an infinite scroll list with a lot of items and the user triggers a pull to refresh, you may want to delete all of the cached list items. To do this, you can supply a group key as the 3rd parameter ofloadFromObservable
.
...
loadList(pageNumber){
leturl="http://google /?page="+pageNumber;
letcacheKey=url;
letgroupKey="googleSearchPages"
letrequest=this.http.get(url);
returnthis.cache.loadFromObservable(cacheKey,request,groupKey);
}
...
Then when pull to refresh is triggered, you can use theclearGroup
method and pass in your group key.
...
pullToRefresh(){
this.cache.clearGroup("googleSearchPages");
}
...
If you want a custom TTL for a single request, you can pass it as the fourth parameter.
letttl=60*60*24*7;// TTL in seconds for one week
letrequest=this.http.get(url);
returnthis.cache.loadFromObservable(cacheKey,request,groupKey,ttl);
this.cache.setDefaultTTL(60*60);//set the default cache TTL for 1 hour
It's automatically done on every startup, but you can do it manually.
this.cache.clearExpired();
!Important!
Make sure that you have akeyPrefix
set in the CacheModule config, otherwise this will clear everything in Ionic Storage.
this.cache.clearAll();
You can disable cache without any issues, it will pass all of the original Observables through and all Promises will be rejected.
this.cache.enableCache(false);
You can also disable invalidating cached items when the device is offline.
this.cache.setOfflineInvalidate(false);
Thanks goes to these wonderful people (emoji key):
Daniel Suchý 🤔📖💻👀 |
Will Poulson 📖💻👀 |
Ibby Hadeed 💻 |
Bowser 💻 |
Vojtěch Tranta 💻 |
Bruno Frare 💻 |
This project follows theall-contributorsspecification. Contributions of any kind welcome!