@ngrx/data - 如何扩展集合缩减器/替换数据服务调用结果的处理?

And*_*len 5 ngrx angular angular-ngrx-data

使用@ngrx/data我想以getWithQuery不同于默认值的方式处理API 调用的结果。

目前,如果这返回一个实体数组,则entityCache直接加载到.

到目前为止,我已经使用了概述中显示的标准模式:

export const entityMetadata: EntityMetadataMap = {
  PurchaseOrder: {}
};
Run Code Online (Sandbox Code Playgroud)
@Injectable({
  providedIn: "root"
})
export class PurchaseOrderService extends EntityCollectionServiceBase<
  PurchaseOrder
> {
  constructor(serviceElementsFactory: EntityCollectionServiceElementsFactory) {
    super("PurchaseOrder", serviceElementsFactory);
  }
}
Run Code Online (Sandbox Code Playgroud)

相反,我想处理以下 API 响应并entities像往常一样将加载到entityCache 中,getWithQuery但也将其粘贴total在我商店的其他地方。

{
    "entities": [{...}, {...}, ..., {...}],    // list of entities
    "total": 100
}
Run Code Online (Sandbox Code Playgroud)

如果返回此 API 响应,我自然会收到以下错误:

在此处输入图片说明

我的理解是,为每个提供EntityCollectionDataService接口和add / delete / getAll / getById / getWithQuery / update方法的实体创建并注册了一个默认的 reducer 。

我想保留这些方法但覆盖getWithQuery减速器以实现我的目标。

这在Customizing Entity Reducer Behavior 中提到

但是很多时候你想用一些在之前或之后运行的额外的减速器逻辑来扩展一个集合减速器。

这怎么可能呢?

如果我尝试getWithQuery在我的内部覆盖,我仍然会收到上述错误PurchaseOrderService

  getWithQuery(params) {
    return super.getWithQuery(params).pipe(tap(result => console.log(result)));
  }
Run Code Online (Sandbox Code Playgroud)

And*_*len 4

设法使用自定义EntityDataService使其正常工作

@Injectable()
export class PurchaseOrderDataService extends DefaultDataService<
  PurchaseOrder
> {
  constructor(
    http: HttpClient,
    httpUrlGenerator: HttpUrlGenerator,
    logger: Logger,
    config: DefaultDataServiceConfig
  ) {
    super("PurchaseOrder", http, httpUrlGenerator, config);
  }

  getWithQuery(params: string | QueryParams): Observable<PurchaseOrder[]> {
    return super.getWithQuery(params).pipe(
      tap(res => console.log(res)),
      map((res: any) => res.entities)
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

那么需要注册这个:

@NgModule({
  providers: [PurchaseOrderDataService] // <-- provide the data service
})
export class EntityStoreModule {
  constructor(
    entityDataService: EntityDataService,
    purchaseOrderDataService: PurchaseOrderDataService
  ) {
    entityDataService.registerService(
      "PurchaseOrder",
      purchaseOrderDataService
    ); // <-- register it
  }
}
Run Code Online (Sandbox Code Playgroud)

并同时导入它EntityDataModule.forRoot({ entityMetadata }),