简体   繁体   English

如果两个Flux商店必须相互依赖怎么办?

[英]What if two Flux stores have to depend on each other

One of the goals of Flux is to make the app more predictable by reducing crazy tangled dependencies. Flux的目标之一是通过减少疯狂纠结的依赖关系来使应用程序更具可预测性。 Using the Dispatcher you can define a strict order in which the Stores are updated. 使用Dispatcher,您可以定义更新商店的严格顺序。 That creates a nice tree dependency hierarchy. 这创建了一个很好的树依赖层次结构 That's the theory. 这就是理论。 Consider following situation: 考虑以下情况:

I have a game. 我有一场比赛。 The store sitting at the top of the hierarchy is StateStore that holds only the current game state, ie playing , paused , over . 位于层次结构顶部的商店是StateStore ,它只保存当前游戏状态,即播放暂停结束 It is updated via actions like PAUSE or RESUME . 它通过PAUSERESUME等操作进行更新。 All other stores depend on this one. 所有其他商店都依赖于这个。 So when a store handles some kind of update action (ie MOVE_LEFT ), it first checks the StateStore and if the game is paused or over , it ignores the action. 因此,当商店处理某种更新操作(即MOVE_LEFT )时,它首先检查StateStore,如果游戏暂停结束 ,则忽略该操作。

Now let's say that there is an action that would cause game over. 现在让我们说有一个动作会导致游戏结束。 It updates some store and the store decides that the game shouldn't continue ( "the game character moves left and falls into a trap" ). 它更新了一些商店,商店决定游戏不应该继续( “游戏角色向左移动并陷入陷阱” )。 So the state in the StateStore should change to over . 所以StateStore中的州应该改为结束 How do I do that? 我怎么做?

Theoretically, it should go like this: 从理论上讲,它应该是这样的:

  1. The given store is updated first and reaches the point of game over 给定的商店首先更新并到达游戏结束点
  2. The StateStore is updated afterwards (it waitsFor the other store), checks the other store and switches the state to over . 之后更新StateStore(它等待另一个商店),检查另一个商店并将状态切换为结束

Unfortunately, the other store needs to access the StateStore as well to check the current game state to see if it should be updated at all (ie the game is not paused). 不幸的是,其他商店也需要访问StateStore来检查当前的游戏状态,看它是否应该更新(即游戏没有暂停)。 They clearly depend on each other. 他们显然相互依赖。

Possible solutions: 可能的解决方案:

  1. Merge such stores into one store. 将这些商店合并到一个商店。 That would probably cause my whole app to collapse into a single store which brings up the question whether Flux in this case is a good idea. 这可能会导致我的整个应用程序崩溃到一个商店,这提出了一个问题,在这种情况下Flux是一个好主意。
  2. Distinguish update order and read-only dependencies. 区分更新顺序只读依赖项。 All stores would be updated in a strict order, however they could read from each other arbitrarily. 所有商店都会按严格的顺序更新,但他们可以随意阅读。 The StateStore would therefore for every action check all existing stores and if any of them indicated game over, it would change the state to over , effectively preventing all other stores from updating. 因此,StateStore会对每个操作检查所有现有商店,如果其中任何一个指示游戏结束,它会将状态更改为结束 ,从而有效地防止所有其他商店更新。

What do you think? 你怎么看?

In Flux stores should be as independent from each other as possible and should not read from each other. Flux中,商店应尽可能彼此独立,不应相互阅读。 The only way to change their state is through actions. 改变状态的唯一方法是通过行动。

In your case, if some store decides that the game is over — you should update a StateStore from the ActionCreator. 在您的情况下,如果某个商店决定游戏结束 - 您应该从ActionCreator更新StateStore。 You can do it by calling a HaltGameActionCreator from the store or by dispatching a HALT_GAME action from ActionCreator that triggered the store change in the first place. 您可以通过从商店调用HaltGameActionCreator或从ActionCreator调度HALT_GAME操作来实现,该操作首先触发了商店更改。

For those having the same issue, you can read here about the actual application I had this problem with and how I approached it. 对于那些有相同问题的人,你可以在这里阅读我遇到这个问题的实际应用程序以及我如何处理它。 Long story short, I allowed all the stores to arbitrarily read from each other (the suggested solution no. 2). 长话短说,我允许所有的商店互相任意阅读(建议的解决方案2)。

Note that ES6 modules allow circular dependencies which simplifies the implementation. 请注意,ES6模块允许循环依赖,这简化了实现。

Nevertheless, looking back I'm not sure if it was a right decision. 然而,回头看,我不确定这是不是一个正确的决定。 If a piece of business logic inherently contains a circular dependency, we should not try to apply a solution that doesn't really support it just because somebody says so. 如果一个业务逻辑固有地包含循环依赖,我们不应该尝试应用一个不真正支持它的解决方案,因为有人这么说。 Flux is only one pattern, there are many other ways how to structure the code. Flux只是一种模式,还有很多其他方法来构造代码。 So perhaps I would recommend collapsing the whole logic into a single store and use one of the other ways to implement the store itself (eg standard OOP techniques). 所以也许我会建议将整个逻辑折叠到一个存储中,并使用其他方法之一来实现存储本身(例如标准OOP技术)。

I would also consider using redux with reselect instead of Flux. 我也考虑使用终极版重选 ,而不是流量。 The problem with the original example is with the StateStore that depends on two different inputs. 原始示例的问题在于StateStore依赖于两个不同的输入。 It can be changed either by the user explicitly pausing/resuming the game, or by the game situation reaching game over. 它可以通过用户明确地暂停/恢复游戏来改变,或者通过游戏情况到达游戏结束来改变。 The advantage of this approach is that you need to check only one store to get the current game state. 这种方法的优点是您只需要检查一个商店即可获得当前的游戏状态。

With redux/reselect, you'd have one reducer handling pause/resume actions and another reducer handling the game situation . 使用redux / reselect,你有一个reducer处理暂停/恢复动作和另一个处理游戏情况的 reducer。 Then you'd have a selector combining these two pieces of information into the final game state. 然后你会有一个选择器将这两个信息组合成最终的游戏状态。 Most of the business logic would be moved from the stores to action creators, ie, in the moveLeft() action creator, you'd use this selector to check the game state and only then you'd dispatch MOVE_LEFT action. 大多数业务逻辑将从商店移动到动作创建者,即,在moveLeft()动作创建者中,您将使用此选择器来检查游戏状态,然后您才会调度MOVE_LEFT操作。

Note that this is just a rough idea and I don't know if it's viable. 请注意,这只是一个粗略的想法,我不知道它是否可行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM