NgRx:倾听服务中的状态变化而不是使用效果

时间:2017-11-17 14:19:21

标签: angular ngrx ngrx-effects

我的问题是:服务是否可以监听状态更改并根据状态值进行http调用,还是必须由效果(NgRx)触发? 因此,与通常在网络上找到的示例中的效果所调用的服务不同,您可以使用服务来监听商店的某个部分,并根据该服务做出反应。因此没有更多的影响。 我的问题更多的是哲学(最佳实践)问题,而不是技术问题,因为从技术上讲,两者都有效。

更新

以下是一个具体案例,以了解我为什么要问:

背景:

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

目前的实施:

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

问题:

问题是状态未使用新过滤器更新。我可以在我的reducer中捕获FILTER_ELEMENTS动作并更新状态,但这会导致其他几个潜在的问题。 首先会调用哪种效果和减速器? 如果有后端错误怎么办?我的状态使用新过滤器更新,但列表未过滤。 异步主义怎么样?如果我在服务器回答之前或更新状态之前要求另一个过滤器怎么办?

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

所以我的问题是: 那商店真的是真相的重要来源吗?而不只是一个" log"发生的事情可能是也许不是最新的。我的意思是,想要添加过滤器的组件可以通过调度ADD_FILTER操作来执行此操作,该操作将更新状态中的过滤器列表。我的服务可以监听过滤器列表,并在每次列表更改时调用后端。 因此,当状态发生变化时,服务仅调用后端,并且我们知道最新的实际状态。然后发出成功"使用更新列表对商店执行操作。 我不知道这会产生更多潜在的无限循环而不是效果......毕竟,效果也会导致无限循环...... 因此,我的服务实际上是一种收听商店更改的效果,而不是直接收听操作。

1 个答案:

答案 0 :(得分:4)

您不应该这样做,因为它明确违反了单向数据流。异步事件导致操作更新存储,来自存储的数据不会触发可能反过来触发新操作的新异步事件。这会产生严重错误的可能性,例如无限的事件循环,并且还使您的应用程序难以推理。因此,效果服务存在,以确保永远不会违反单向数据流。

使用ngrx记住一个动作代表整个应用程序状态的变化,完全停止是很重要的。效果服务本质上需要一个操作,需要一些远程资源来描述完整的状态更改并抓取该远程资源并将其映射到一个新的操作,该操作在它到达商店之前表示完整的状态更改。如果您根据商店的内容进行进一步的状态更改,那么显然您没有完全描述您的操作中的状态更改。

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

编辑以解决其他问题:

商店是设计的唯一真实来源,IE,应用程序的状态不经过商店就不会更新。作为开发人员,您可以执行此操作。它不应该是追溯性地更新它以反映"发生了什么",它应该是实际的变化,商店正在存储您的应用程序的状态。

就目前而言,似乎您想要过滤元素,然后通过调度UPDATE_FILTERS操作来响应接收这些元素,这是100%错误的过程。

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

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

所有这些都可以在框架中解决,你的特效服务不应该导致无限循环,如果可以的话,你设计错了,可能是试图访问效果服务中的状态。但是你永远不应该对采取新行动的行动做出反应。