商店之间的循环模块依赖关系

时间:2016-05-26 11:00:45

标签: react-native flux reactjs-flux

在我追踪乐器练习的本机应用程序中,我有三个商店:

  • SessionStore
  • GoalStore
  • InstrumentStore

每个商店都管理一个模型(会话,目标,工具)并通过REST API获取/更新服务器。

SessionStore监听有关会话的操作(显然):session.add,session.update。但它也会监听其他商店的更改,以便在目标或工具更改名称时更新会话。

相应地,InstrumentStore会监听工具操作,也会监听会话操作以更新有关会话使用特定工具的统计数据。

为了能够没有竞争条件,InstrumentStore将对动作session.add起作用,但是等待SessionStore首先处理动作(以确保在API中更新了Session)。为此,我使用dispatcher.waitFor和SessionStore dispatchToken作为信号量。

问题:由于所有商店都使用dispatchTokens,所以他们都必须互相导入。这是对模块的循环依赖,导致奇怪的竞争条件。有时,其中一家商店包含其中一家商店。

以下是我的商店:https://github.com/osirisguitar/GuitarJournalApp/tree/feature/flat-ui/js/stores

我是否以错误的方式使用助焊剂图案?

加成

这就是我想要发生的事情(按顺序):

会话更新:

  1. 将更新的会话发送到API
  2. 刷新SessionStore
  3. 刷新GoalStore
  4. 刷新InstrumentStore
  5. 2,3和4需要等待1才能完成,这就是为什么GoalStore和InstrumentStore需要SessionStore调度令牌。

    目标是更新:

    1. 将更新的目标发送到API
    2. 刷新GoalStore
    3. 刷新SessionStore
    4. 2和3需要等待1,这就是为什么SessionStore需要引入循环依赖的GoalStore dispatchToken。

1 个答案:

答案 0 :(得分:1)

你有一些重复。

所有商店都会听到所有的调度。这就是拥有一名调度员的美妙之处。因此,当您发送sessions.addsessions.update动作时,您会点击三个不同的商店,其中两个正在执行完全相同的操作。这是一个禁忌。

通常,每个商店的调度令牌只应负责更新 商店。因此,您的目标和工具商店应该更新SessionsStore。 .refresh.emit应仅在SessionsStore调度令牌中发生。

编辑以回答您编辑的问题。

我认为您的困惑是因为您没有意识到dispatcher.register接受函数作为其参数,而不是对象。

JS中的函数不会在声明中评估其内容。它们仅在执行时进行评估。

简单的例子;

func = function(){ console.log(testVar) } // No error, even though testVar is undefined
func() // ERROR: testVar is undefined
var testVar = 'hey';
func() // log: 'hey';

dispatcher.register接受一个函数作为输入,并返回一个键(格式为ID_#)。该密钥由调度程序本身生成,而不运行输入函数。输入函数只是存储起来以供以后使用,并在每次调度有效负载时运行。

这意味着在第一次发货之前,您不需要定义内部变量。而且因为你想要在你创建商店之前发送任何东西,这就变成了无问题。

但这也意味着默认情况下,调度程序对自身具有一种循环依赖性(依赖于它自身函数的返回值,存储在外部变量中)。但那是调度员的设计。除非你打算写一个新的调度员,否则这只是交易的一部分。

还值得指出的是,如果通过调用多个waitFor来实现真正的循环依赖关系,那么调度程序将正确地抛出一个错误,并说明这一点;

Dispatcher.waitFor(...): Circular dependency detected while waiting for ID_#