loading...

Base Class for Akita Entities

jengfad profile image Jennifer Fadriquela ・1 min read

If you are using Akita for state management, this article might be helpful to you.

// BaseEntityService.ts
import { Observable } from 'rxjs';
import { BaseQuery } from './BaseQuery';
import { EntityStore, EntityState } from '@datorama/akita';
import { tap, delay } from 'rxjs/operators';

export abstract class BaseEntityService<TParams, TView, TResult> {

    constructor(
        protected query: BaseQuery<TView, TParams>,
        protected entityStore: EntityStore<EntityState<TView>, TView>
        ) {
    }

    protected abstract getFromApi(params: TParams): Observable<TResult>;
    protected abstract getFromStore(params: TParams): Observable<TResult>;

    protected selectFromStore(params: TParams): Observable<TView> {
        return this.query.selectData(params).pipe(
            delay(1), // if removed, ui will not update with current data
        )
    }

    get(params: TParams): Observable<TResult> {
        return this.toggleLoading(
            () => {
                if (!this.query.hasData(params))
                    return this.getFromApi(params);
                else
                    return this.getFromStore(params);
            }
        );
    }

    private toggleLoading<TResult>(o: () => Observable<TResult>) {
        this.entityStore.setLoading(true);
        return o().pipe(
            tap((x) => {
                this.entityStore.setLoading(false);
            })
        )
    }
}

BaseEntityService handles abstraction for getting data from api or store. It also implements custom setting of entity loading property via toggleLoading.

// BaseQuery.ts
import { EntityState, QueryEntity } from "@datorama/akita";
import { filter } from 'rxjs/operators';

export abstract class BaseQuery<TView, TParams> extends QueryEntity<EntityState<TView>, TView> {
    selectData(params: TParams) {
        const key = JSON.stringify(params);
        return this.selectEntity(key).pipe(
            filter(x => !!x)
        )
    }

    selectDataNullable(params: TParams) {
        const key = JSON.stringify(params);
        return this.selectEntity(key);
    }

    hasData(params: TParams) {
        const key = JSON.stringify(params);
        return this.hasEntity(key);
    }
}

BaseQuery contains custom selection of existing store data. In our app, we use stringified parameters as keys.

Discussion

pic
Editor guide