Caching Support

Akita has built-in cache support that will provide information about whether you already have data in the store. For example, in many cases we want to perform an HTTP request only once, and from that point on, to get the cached data from the store.

Now, when we call EntityStore.set(), Akita internally marks the store as cached. We can also manually mark the store as cached by calling the Store.setHasCache(boolean) method.

Akita exposes two query methods that you can use to query the cache value - selectHasCache() and getHasCache().

In addition to that, it exposes the cacheable function. This method takes a Store and an observable. When we call it, it'll subscribe to the observable only if the cache value is currently false. Otherwise, it'll return EMPTY observable.

products.service.ts
import { cacheable } from '@datorama/akita';
export class ProductsService {
constructor(private productsStore: ProductsStore,
private http: Http) {}
getProducts() {
const request$ = this.http.get().pipe(
tap(products => productsStore.set(products)
);
return cacheable(this.productsStore, request$);
}
}

But that’s not all — we can also define a ttl (time to live) which when expires will automatically invalidate the cache for you. For example:

products.store.ts
@StoreConfig({
name: 'products',
cache: {
ttl: 3600000
}
})
export class ProductsStore extends EntityStore<ProductsState> {
constructor() {
super();
}
}
products.service.ts
import { EMPTY } from 'rxjs';
export class ProductsService {
constructor(private productsStore: ProductsStore,
private productsQuery: ProductsQuery,
private http: Http) {}
getProducts() {
return this.productsQuery.selectHasCache().pipe(
switchMap(hasCache => {
const apiCall = this.http.get(..).pipe(
tap(products => this.productsStore.set(products))
);
return hasCache ? EMPTY : apiCall;
})
)
}
}

In the code above, every hour Akita invalidates the cache, which causes the selectHasCache() stream to fire, causing the products to be fetched again from the server.