Cache Functionality

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.

The way we use it is by using two new query methods — selectHasCache() and getHasCache() . For example:

export class ProductsService {
constructor(private productsStore: ProductsStore,
private productsQuery: ProductsQuery,
private http: Http) {}
getProducts() {
const request$ = this.http.get(..).pipe(
tap(products) => productsStore.set(products)
);
return this.productsQuery.getHasCache() ? of() : request$;
}
}

We can make it event shorter by using the cacheable helper function:

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
products.service.ts
@StoreConfig({
name: 'products',
cache: {
ttl: 3600000
}
})
export class ProductsStore extends EntityStore<ProductsState> {
constructor() {
super();
}
}
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) => 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.

Basic Store Usage

It can also be used with the basic store:

store.ts
service.ts
@StoreConfig({
name: 'storeName',
cache: {
ttl: 3600000
}
})
export class SomeStore extends Store<State> {
constructor() {
super(initialState);
}
}
import { EMPTY } from 'rxjs';
import { cacheable } from '@datorama/akita';
export class SomeService {
constructor(private store: SomeStore,
private http: Http) {}
getData() {
const request$ = this.http.get(..).pipe(
tap(data => {
this.store.update(data);
this.store.setHasCache(true, { restartTTL: true })
})
);
return cacheable(this.store, request);
}
}