angular - 如何使用 Entity Effects 扩展 ngrx/data?

标签 angular ngrx-effects angular-ngrx-data ngrx-data

在将应用程序转换为使用 ngrx 状态管理时,我决定通过 EntityMaps 使用 ngrx/data 管理某些模型的状态。到目前为止这工作正常,但是当事情变得有点复杂时,例如基于从远程服务器获取的模型数据,我需要相关模型(订单->产品或 REST 端点格式 GET orders/:id/products)

我觉得卡住了 - 我知道有 ngrx/effects 可以触发在使用 ngrx 时加载其他数据的操作,并且在此 ngrx/data guide , `EntityEffects 被提到会触发 Action 的副作用,但除此之外,文档似乎还在进行中,现在对我帮助不大。

不幸的是,没有太多关于扩展 EntityEffects 以自定义远程数据获取的内容。当然,我可以一路向下实现选择器、 Action 、缩减器、影响标准的 ngrx 方式,但 ngrx/data 的全部意义在于用更少的样板代码使状态处理更容易,并充当包装器围绕 ngrx,隐藏默认/样板代码但仍然提供使用底层部分的方法?

由于我对 ngrx 和一般的状态管理还比较陌生,所以我不知道去哪里寻找最佳实践或推荐的解决方案,以及如何处理这个问题。

所以我的问题基本上是:

  1. 我如何才能同时使用 ngrx/data 并通过 ngrx/effects 或 EntityEffects 加载(相关)模型数据?
  2. 我在哪里扩展适当的服务/类,而不必手动实现每个 reducer/action,而是让 ngrx/data 来处理?

我已经搜索了 Stackoverflow、Gitter 并询问了同事,但都没有成功 - 或者我是否让它变得比它必须的更复杂?如果是这样,我感谢您的帮助。

注意:这个问题特别针对ngrx/

最佳答案

这是一个开放的 github 问题 https://github.com/ngrx/platform/issues/1934


不过,我相信有一种方法可以做到这一点,而无需使用 EntityCacheDispatcher 的 saveEntities 方法完全从头开始 Save with EntityCacheDispatcher.saveEntities() .

为了让您了解按预期使用时它是如何工作的,这是我对最近项目的保存顺序效果

  saveOrder$ = createEffect(() =>
    this.actions$.pipe(
      ofType(PurchaseOrderActions.saveOrder),
      switchMap(() => {
        const order$ = this.store.pipe(select(selectHeader));
        const orderLines$ = this.store.pipe(select(allLines));
        const deletedOrderLines$ = this.store.pipe(select(selectDeletedLines));
        return combineLatest([order$, orderLines$, deletedOrderLines$]).pipe(
          first(),
          switchMap(([order, lines, deletedLines]) => {
            const changes: ChangeSetItem[] = [
              cif.upsert("PurchaseOrder", order),
              cif.upsert("PurchaseOrderLine", lines),
              cif.delete("PurchaseOrderLine", deletedLines)
            ];
            return this.entityCacheDispatcher
              .saveEntities(changes, `${this.baseURL}order`)
              .pipe(
                map(changesResponse =>
                  PurchaseOrderActions.saveOrderSuccess({
                    header: changesResponse.changes[0]
                      .entities[0] as PurchaseOrder,
                    lines: changesResponse.changes[1]
                      .entities as PurchaseOrderLine[]
                  })
                )
              );
          })
        );
      })
    )
  );

潜在路线图

  1. 创建您的自定义操作,例如输入 [OrderProductsPage ONINIT] ONINIT"
  2. 创建调用 saveEntities 的效果
// include in custom action payload and get this id here
const id; 

// changeSet with empty changes
const changeSet = {
    changes: [],
    tag: "CUSTOM_GET_PRODUCTS" // hook for defining custom behaviour
}
this.entityCacheDispatcher.saveEntities(changeSet, `orders/${id}/products`)
  1. 扩展 EntityCacheDataService 并覆盖 saveEntities 方法以首先检查标签是否为 CUSTOM_GET_PRODUCTS 否则调用 super.saveEntities(changeSet, url)。如果标签是 CUSTOM_GET_PRODUCTS,则调用 get http 并将管道映射到带有 ChangeSetOperation.Add
  2. 的 changeSet

引用super.saveEntities()

更新

这行得通,但它比我想要的更 hacky

Stackblitz

关于angular - 如何使用 Entity Effects 扩展 ngrx/data?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60256840/

相关文章:

angular - 没有带有ngrx/效果的HttpHandler的提供者

angular - NGRX 效果 : Dispatch multiple actions individually

angular - ngrx/data 实体数据服务

Angular 默认路由器 socket

javascript - Material Design Table 不接受数据源对象

根据条件隐藏组件的干净方法是什么?

Angular + Ngrx : best practice to select a value in component and in function

angular - 错误类型错误 : Cannot assign to read only property 'isSelected' of object '[object Object]'

javascript - 在 ngrx/effect 中访问商店的正确方法

angular - 支持 ngRx/data 的正确 Angular 版本是什么?