Use indexedDb with ngrx for fast angular bootstrap

David Palita
WhozApp
Published in
2 min readAug 3, 2018

At whoz.com, we have an intensive use of ngrx. We paired it with indexedDb to load a massive initial state in a snap.

We find ngrx so great and so useful, that we’ve put most of the data handling in the angular frontend, and rely on the spring cloud backend for security, long term persistence and sensitive business logic.

This means that we load a bunch of data at application bootstrap. We wanted to store the last known state on the client side to allow for fast bootstraps after the very first load of the app. A first prototype with localStorage worked great until we reached the dreaded 10MB limit in chrome.

That’s where it became interesting because:

  • indexedDb could hold a virtually infinite amount of data :-)
  • indexedDb is asynchronous :-|
  • ngrx initialization and reducers are not :-(

Here is what we did, note that it also relies on your reducers being a bit smarter than the pure functions they are. You can read about how we use injected services in reducers.

Angular provides a way to execute code before the app initialization by providing functions to the APP_INITIALIZER multi provider. When those functions return promises, the app initialization is put on hold until they are all resolved.

Provide promises to the angular APP_INITIALYZER to put application initialization on hold until ready

In the promise we’ll access our asynchronous storage and temporarily store our initial state to give it to ngrx later.

Read your indexedDb in a promise but store the state aside for later synchronous access

Then when the promises are resolved (ie. all initial slices of state have been read from indexedDb) we trigger our own AppInitAction. You can know about app initialization via the angular ApplicationInitStatus.

Dispatch your controlled AppInitAction when all reducers are ready to receive an initial state

At last you can listen for this action in your reducer to provide the initial state that you previously stored for synchronous access.

Use the initial state upon receiving the AppInitAction

To sum it up, you can have an asynchronous initial state in ngrx by:

  • loading this initial state in APP_INITIALIZER promises
  • storing this state for later synchronous access by ngrx
  • triggering your own AppInitAction when ApplicationInitStatus.donePromise is resolved
  • listening for this action in your reducer to use the previously stored initial state

It would be much easier if ngrx allowed for an asynchronous initial state factory, watch for this issue where it may happen, and until them I hope this helped :-)

--

--