angular - NgRx:监听服务中的状态变化而不是使用 Effect

标签 angular ngrx ngrx-effects

我的问题是:服务是否可以监听状态变化并根据状态值进行 http 调用,还是必须由 effect(NgRx) 触发? 因此,不是像您通常在 Web 上找到的示例那样通过效果调用服务,而是让服务监听商店的一部分并根据它使用react。因此没有更多的效果。 我的问题更像是一个哲学(最佳实践)问题,而不是技术问题,因为从技术上讲,两者都有效。

更新

这里有一个具体的例子来理解我为什么要问:

上下文:

我有一个从后端收到的元素列表。我可以过滤该元素列表。一次可以有多个过滤器。过滤在后端完成。

当前实现:

该组件调度一个 FILTER_ELEMENTS 操作。该操作由调用 http 服务的效果拾取。该服务向后端询问基于过滤器的元素列表。 因为可以有多个过滤器,效果(或服务)需要知道当前的过滤器是什么并将新过滤器添加到该列表中。所以我在效果中添加了一个 .withLatestFrom(this.state$) 并从那里获取当前的过滤器列表。

问题:

问题是状态没有用新过滤器更新。我可以在我的 reducer 中捕获 FILTER_ELEMENTS 操作并更新状态,但这会导致其他几个潜在问题。 effect 和 reducer 哪个会先被调用? 后台出错怎么办?我的状态已使用新过滤器更新,但列表未被过滤。 asynchornism 呢?如果我在服务器响应之前或状态更新之前要求另一个过滤器怎么办?

这对我来说似乎有点太乱了。

所以我的问题是: 那商店真的是真实的唯一来源吗?而不仅仅是发生的事情的“日志”,它可能是最新的,也可能不是最新的。我的意思是,想要添加过滤器的组件可以通过调度 ADD_FILTER 操作来更新状态中的过滤器列表。我的服务可以监听过滤器列表并在每次列表更改时调用后端。 因此,该服务仅在状态发生变化时调用后端,并且我们知道的是最新的真实状态。然后使用更新后的列表向商店发送“成功”操作。 我看不出这会导致比效果更多的潜在无限循环……毕竟,效果也会导致无限循环…… 因此,我的服务实际上是一种监听存储更改而不是直接执行操作的效果。

最佳答案

您不应该这样做,因为它明显违反了单向数据流。异步事件导致操作去更新存储,从存储中出来的数据不会触发新的异步事件,而新的异步事件又会触发新的操作。这会产生严重错误的可能性,例如无限事件循环,并且还会使您的应用程序难以推理。效果服务就是出于这个原因而存在的,以确保单向数据流不会被违反。

重要的是要记住 ngrx 一个 Action 代表整个应用程序状态的变化,句号。效果服务本质上采取了一个需要一些远程资源来描述完整状态更改的操作,并获取该远程资源并将其映射到一个新操作中,该操作在它到达商店之前确实代表了完整的状态更改。如果您根据商店中出现的内容进行进一步的状态更改,那么很明显您没有在您的操作中完整描述您的状态更改。

重播实际进入商店的操作应该每次都产生相同的状态,同样,如果您根据从商店中获得的内容进行其他状态更改,情况就不会如此。

编辑以解决其他问题:

商店是设计的唯一真实来源,IE,应用程序的状态不通过商店就不会更新。作为开发人员,您有责任强制执行此操作。它不应该是你追溯更新它以反射(reflect)“发生了什么”,它应该是实际的变化,商店正在存储你的应用程序的状态。

就目前而言,您似乎想要过滤元素,然后通过调度 UPDATE_FILTERS 操作对接收到的这些元素使用react,这 100% 是错误的做法。

解决问题的第一步是确保您的操作包含状态更改所需的所有信息,因此,如果您的效果服务需要访问当前状态,则说明您做错了什么。 FILTER_ELEMENTS Action 应该包含所有需要的过滤器,效果服务应该永远不会访问当前状态。

下一步是再次确保您的操作包含状态更改所需的所有信息。不要在你的 reducer 中捕获 FITLER_ELEMENTS,映射到一个新的 Action ,ELEMENTS_FITLERED,它包含过滤的元素和过滤器并对它使用react,并在同一个 Action 中应用两个状态变化。在出现错误的情况下,您可以捕获它并使用创建该状态所需的数据映射到 FILTER_ERROR 操作,其中可能包括旧过滤器。至于在旧过滤器完成之前通过的新过滤器,那么您可以使用 switchMap 来确保查看最新的过滤器并忽略以前的请求。

所有这些都可以在框架中解决,并且您的效果服务不应该导致无限循环,如果可以,则您设计错误,可能是通过尝试访问效果服务中的状态。但是你永远不应该用新的 Action 来回应 Action 。

关于angular - NgRx:监听服务中的状态变化而不是使用 Effect,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47352750/

相关文章:

django - 找不到 ng2-bootstrap 下拉菜单

asp.net - Angular 6 - IE11 上的 GET/POST 问题 - 符号(rxSubscriber)未定义

angular - ngrx/router-store - 路由参数选择器为子路由返回 undefined

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

javascript - 为什么 Angular 2 需要 node.js

javascript - 如何通过 Angular2 使用 REST API?

angular - 何时在 angular2 中使用 ngrx/effect

angular - 选择器不反射(reflect) reducer 中的状态

angular - 如何将 ngrx/store 与 Angular 路由器防护装置连接

angular - 如何使用具有 5 个以上 Action 的 ofType?