3

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

我觉得卡住了——我知道在使用ngrx时有ngrx/effects来触发加载其他数据的动作,在这个ngrx/data guide中,提到了`EntityEffects来触发动作的副作用,但除此之外,文档似乎是正在进行中,现在对我没有多大帮助。

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

由于我对ngrx和一般状态管理相对较新,我不知道在哪里可以找到最佳实践或推荐的解决方案,以及如何处理这个问题。

所以我的问题基本上是:

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

我已经搜索了 Stackoverflow、Gitter 并询问了同事,但没有成功 - 还是我让它变得比它必须的复杂得多?如果是这样,我很感激任何帮助。

注意:这个问题特别是关于 ngrx/

4

1 回答 1

1

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


但是,我相信有一种方法可以做到这一点,而无需使用 EntityCacheDispatcher 的saveEntities方法Save 和 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 和 pipe map 到 changeSetChangeSetOperation.Add

引用super.saveEntities()

更新

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

堆栈闪电战

于 2020-02-28T09:00:46.530 回答