有没有办法使用 NgRx 数据自动检查实体是否在商店中?

问题描述

为了减少网络流量,我需要检查具有给定 id 的实体是否在商店中,如果没有,则应从服务器请求。我找不到任何配置,所以我只是使用 RxJs 硬编码逻辑,如下所示。

有没有办法用 NgRx/NgRx 数据配置它? 有没有办法配置实体可以在商店中停留多长时间而无需重新请求?

import {
  EntityCollectionServiceBase,EntityCollectionServiceElementsFactory,} from '@ngrx/data';
import { Injectable } from '@angular/core';

import { MyEntity } from 'app/state/my-entity/MyEntity';
import { Observable,of,Subject } from 'rxjs';
import { distinct,filter,switchMap,tap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',})
export class MyEntityDataService extends EntityCollectionServiceBase<MyEntity> {

  private id$ = new Subject<string|number>();

  constructor(serviceElementsFactory: EntityCollectionServiceElementsFactory) {
    super('MyEntity',serviceElementsFactory);

    // Fetching the data if not yet there
    this.id$.pipe(
      // Preventing multiple requests e.g. when multiple components
      // are requesting the same data
      distinct(),switchMap(
        (id: string|number): Observable<MyEntity | undefined> => this.filteredEntities$.pipe(
          switchMap(
            (entityCollection: MyEntity[]): Observable<MyEntity | undefined> => {

              const thatEntity: MyEntity | undefined =
                entityCollection.find((entity: MyEntity) => `${entity.id}` === `${id}`);

              return of(thatEntity).pipe(
                filter((v: MyEntity | undefined): boolean => !v),tap(() => super.getByKey(id))
              )
            }
          ),),).subscribe();
  }

  getByKey(id: string|number): Observable<MyEntity> {

    this.id$.next(id);

    return this.filteredEntities$.pipe(
      switchMap(
        (entityCollection: MyEntity[]) : Observable<MyEntity> => {
          const thatEntity: MyEntity | undefined = entityCollection.find(
            (entity: MyEntity) => `${entity.id}` === `${id}`
          );
          return thatEntity ? of(thatEntity) : of();
        }
      ),);
  }
}

解决方法

我遇到了同样的问题,对我来说最好的解决方案是在发送 action 之前检查它的效果。

//selectIdExists:selector recieve ID and return true if loaded or false if not found
//user should dispatch initialFindById and the effect will decide either to dispatch findById or no dispatching

initialFindById$ = createEffect(() => this.actions$.pipe(
        ofType(actions.initialFindById),mergeMap(action => this.store.select(selectors.selectIdExists(action.id))
            .pipe(
                filter(found => found == false),//Id not found 
                map(() => actions.findById({ id: action.id })),))
    ));

如果您想确保即使商店上有数据也能获取数据,只需派发 findbyId 操作

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...