在我追踪乐器练习的本机应用程序中,我有三个商店:
每个商店都管理一个模型(会话,目标,工具)并通过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
我是否以错误的方式使用助焊剂图案?
加成
这就是我想要发生的事情(按顺序):
会话更新:
2,3和4需要等待1才能完成,这就是为什么GoalStore和InstrumentStore需要SessionStore调度令牌。
目标是更新:
2和3需要等待1,这就是为什么SessionStore需要引入循环依赖的GoalStore dispatchToken。
答案 0 :(得分:1)
你有一些重复。
所有商店都会听到所有的调度。这就是拥有一名调度员的美妙之处。因此,当您发送sessions.add
或sessions.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_#