ionic-cache-observable
v0.0.6
Published
Ionic cache service to sync observables with local storage.
Downloads
37
Maintainers
Readme
ionic-offline-observable
Simple module to cache observables to local storage and get or refresh their values across your app. This improves performance by only executing observables once, and allows your app to show the cached content when offline or before content is loaded on a slow connection.
Installation
Install the package:
npm install --save ionic-cache-observable
Import in your project app.module.ts
:
@NgModule({
imports: [
IonicModule.forRoot(App),
IonicStorageModule.forRoot(),
CacheModule,
...
]
})
Blog post
Read about using the module or try out the sample Ionic app on Medium.
Usage example
You have a page, ShoppingListPage
, that shows the user's shoppinglist.
The shopping list is normally retrieved from your server with your ShoppingListProvider
service.
With the implementation below, it is either retrieved by local storage OR from the provider.
constructor(private cacheService: CacheService,
private shoppingListProvider: ShoppingListProvider) { }
ionViewWillEnter() {
// The observable you normally get items from server with.
let shoppingListObservable: Observable<ShoppingList> = this.shoppingListProvider.get();
this.cacheService
.register('shoppingList', shoppingListObservable)
.mergeMap((cache: Cache<ShoppingList>) => cache.get())
.subscribe((shoppingList) => {
// The shopping list is retrieved from local storage,
// or in the case that it doesn't exist in storage yet;
// by triggering your shoppingListObservable.
this.shoppingList = shoppingList;
});
}
refreshShoppingList() {
this.cacheService
.get('shoppingList')
.mergeMap((cache: Cache<ShoppingList>) => cache.refresh())
.subscribe((shoppingList) => {
// The shopping list was just "refreshed" by calling the
// shoppingListProvider observable that was registered with the cache.
this.shoppingList = shoppingList;
});
}
A more flexible approach is to use the BehaviorSubject. This also allows you to easily refresh and get the cached shopping list at the same time:
private cache: Cache<ShoppingList>;
private cacheSubscription: Subscription;
ionViewWillEnter() {
this.cacheSubscription = this.cacheService
.register('shoppingList', shoppingListObservable)
.mergeMap((cache: Cache<ShoppingList>) => {
this.cache = cache;
// We can call refresh already. The refreshed value will be
// passed to the get$ BehaviorSubject.
this.cache.refresh().subscribe();
return this.cache.get$;
}).subscribe((shoppingList) => {
// This is a long-lived Observable that will be triggered when the
// Cache is first initialized with the locally stored value,
// and whenever refresh is called.
this.shoppingList = shoppingList;
});
}
refreshShoppingList() {
// Just call refresh, the cacheSubscription takes care of the rest.
this.cache.refresh().subscribe();
}
Make sure to unsubscribe when needed, ie in ionViewWillLeave
.
Functionality
Keep in mind: When registering a Cache, it will immediately load the locally stored value to memory.
Cache.isEmpty
can be used to determine if the cache has a value. If it is empty, it will automatically try to refresh.NULL
values can be a problem in determining if the cache is empty and should be refreshed.Depending on your application flow, use
CacheService.register
orCacheService.get
.- If you need to use the same
Cache
object on multiple pages, you can eitherregister
it globally first (ie yourAppComponent
,app.ts
) andget
it on all the pages. - Or you can register the same cache multiple times. It is perfectly legal and will not invalidate existing cache objects,
simply update its internal
Observable
, unless the overwrite parameter is set to falseregister(name, false)
. - But don't
register
the same cache with a completely different observable, and don'tget
caches that hasn't been registered.
- If you need to use the same
Advanced usage might have you re-registering the cache with a more detailed observable.
- First it's registered with
shoppingListProvider.get()
- On a deeper page, you can re-register with
shoppingListProvider.get({include: 'users'})
, because that page needs the the shopping list's owners. - The deeper page would first display the cached value (without owners) and then when the refreshed value arrives, add the user info.
- First it's registered with
Contribution
This is just something I threw together quickly because I needed a simple, reusable solution to support offline apps.
However, I will maintain the project and welcome any contributions.