Proponents of ngrx claim (here for example) that you can and should keep all your application state in a single Store. That would suggest the @ngrx/Store can be used for caching because the contents of the cache is a type of application state.
A cache in a web-application is a thing that returns data when it has it, and encapsulates the requesting of the data from the server when it doesn’t. The Wikipedia article on caching calls it a cache hit when the data is available and a cache miss when it isn't.
From a functional programming perspective we can immediately see that reading data from a cache is functionally-impure - it has a side-effect which is that data may be requested from the server and retained in the cache. I don't know how to do this with ngrx which, for example, requires its Selectors to be functionally-pure.
It might help to consider this Caching With RxJs Observables in Angular tutorial (rxjs is said to be extremely complementary to ngrx). We don't have to scroll far to find the getFriends()
function complete with side-effect:
getFriends() {
if(!this._friends){
this._friends = this._http.get('./components/rxjs-caching/friends.json')
.map((res:Response) => res.json().friends)
.publishReplay(1)
.refCount();
}
return this._friends;
}
Also the contents of the Store seem to be universally available to the entire application. The only controls are on how the state can be updated, but it is foolish to go poking around in a cache's raw data unmediated because there are no guarantees about which cache items are available and which are not available.
Hopefully these concerns can be relieved and there's a way of doing this that I've missed. Please can you show me a good way to go about using @ngrx/Store as a cache?
Ngrx is a group of Angular libraries for reactive extensions. Ngrx/Store implements the Redux pattern using the well-known RxJS observables of Angular 2. It provides several advantages by simplifying your application state to plain objects, enforcing unidirectional data flow, and more.
GET requests can be cached. They just get data from the server without changing them. If no POST , PUT , or DELETE request occurs before the next GET request, the data from the last GET request does not change. We simply return the previous data or response without hitting the server.
Where Does NgRx Store Data? NgRx stores the application state in an RxJS observable inside an Angular service called Store. At the same time, this service implements the Observable interface.
You can do something like this
friends$ = createEffect (() =>{
this.actions$.pipe(
.ofType(ListActions.LOAD)
.withLatestFrom(
this.store.select(fromSelectors.loadedList),
(action: fromList.Load, store: fromList.State) => store.friends
)
.switchMap((friends: Friend[]) => {
if (friends) {
return [new ListActions.Loaded(friends)];
}
return this.http
.get('/friendApi')
.map((friends: Friend[]) => new ListActions.Loaded(friends))
.catch(err => Observable.of(new ListActions.Failed()));
});
}
With ‘withLatestFrom’ operator, we get the store (loaded list) state into our effect with the dispatched action and check if the list is filled if so; dispatch the existing list otherwise make the rest call and update our store in the reducer. For a detailed answer refer to this Medium post
In ngrx there are reducers (pure functions) which change the state (or cache) if you will. Those reducers get triggered by actions which you dispatch on the store.
From the store you request slices of data by selectors and subscribe to their changes.
To implement a cache logic you check if data is available and if not you dispatch an action like "LoadDataSliceAction" which would trigger a side Effect which then loads the data into the store.
Does this help?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With