Skip to content

State Store Implementation

Alex Wilson edited this page Sep 30, 2021 · 1 revision

This is a work in progress and is subject to change. Changes and code can be found in its own feature branch.

The state-store implementation we are going with is a 'hub like' implementation where each service is comprised of:

  • A service that only creates http clients and makes requests.
  • A store service that does business logic with these request responses (like applying them to their respective store).

The aim of this implementation is to bring down the amount of API calls each client of the website needs to make, in order to have all the data needed for its components. Its also provides a layer of abstraction between the API endpoints and the clients components.

The Store part of this implementation are a set of BehaviourSubjects and Observables that components can subscribe to, check if it has data, and only send a API request if it does not. This works because we know when the client is needing data (usually after a user event) and so can keep our stores up to date client side without having to make extra API calls each time we the clients user has made a change. (Rather than saving then getting, we just put our objects into the store) it also means that components don't all fire this API call, and instead just get it from the store.

Bellow is an example store.

  // Map Stats
   private _mapStats: BehaviorSubject<GlobalMapStats> = new BehaviorSubject(null);
   public readonly mapStats$: Observable<GlobalMapStats> = this._mapStats.asObservable();

   set mapStats(newMapStats: GlobalMapStats) {
     this._mapStats.next(newMapStats);
   }

   get mapStats() {
     return this._mapStats.value;
   }

The getter and setter here allows some components that only need data once to still be able to call upon the data like a normal property. A component would access this data like so:

   this.statsService.mapStats$.pipe(
      takeUntil(this.destroy$),
      map((c) => {
        if(c) {
          this.globalMapStats = c;
        } else {
          this.statsService.setGlobalBaseStats();
        }
      }),
    );