2016-05-26 7 views
0

В моей реакции родное приложение, которое отслеживает инструмент практики у меня есть три магазина:Круговые зависимостей модуля между магазинами

  • SessionStore
  • GoalStore
  • InstrumentStore

хранит каждый управлять одной модели (Сеанс, цель, инструмент) и получение/обновление сервера с помощью REST api.

SessionStore прослушивает действия, касающиеся сеансов (очевидно): session.add, session.update. Но он также прослушивает изменения в других магазинах, чтобы иметь возможность обновлять сеансы, если имя цели или инструмента изменено.

Соответственно, InstrumentStore прислушивается к действиям инструмента, а также к действиям сеанса для обновления статистики о том, сколько сеансов использует конкретный инструмент.

Чтобы иметь возможность не иметь условий гонки, InstrumentStore будет действовать на action session.add, но дождаться, когда SessionStore обработает действие первым (чтобы гарантировать, что Session был обновлен в API). Для этого я использую dispatcher.waitFor с SessionStore dispatchToken как семафор.

Проблема: поскольку все магазины используют друг друга dispatchTokens, все они должны импортировать друг друга. Это круговая зависимость от модулей и приводит к странным условиям гонки. Иногда один из магазинов не был построен, когда он входит в один из других магазинов.

Вот мои магазины: https://github.com/osirisguitar/GuitarJournalApp/tree/feature/flat-ui/js/stores

Могу ли я с помощью потока шаблона неправильного пути?

Добавление

Это то, что я хочу, чтобы это произошло (в последовательности):

Session обновляется:

  1. Отправить обновленный сеансовый API
  2. Обновить SessionStore
  3. Обновить GoalStore
  4. Обновить InstrumentStore

2, 3 и 4 нужно дождаться завершения 1, поэтому для GoalStore и InstrumentStore нужен токен отправки SessionStore.

Цель является обновление:

  1. Отправить обновленный цель API
  2. Обновить GoalStore
  3. Обновить SessionStore

2 и 3 нужно ждать 1, поэтому SessionStore нуждается GoalStore dispatchToken, который вводит круговую зависимость.

ответ

1

У вас есть некоторое дублирование.

Все магазины будут слышать все отправления. В этом есть красота одного диспетчера. Поэтому, когда вы отправляетеили sessions.update, вы попадаете в три разных магазина, и двое из них делают то же самое. Это не-нет.

Как правило, токен отправки магазина должен отвечать только за обновление , что магазин. Поэтому ваши магазины Goal and Instrument должны не обновлять SessionStore. .refresh и .emit должны выполняться только в токенах отправки SessionStore.


EDIT ответит на ваш отредактированный вопрос.

Я думаю, что ваше замешательство связано с тем, что вы не признаете, что 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_#). Этот ключ генерируется самим диспетчером без запуска функции ввода. Функция ввода просто сохраняется для последующего использования и запускается каждый раз при отправке полезной нагрузки.

Это означает, что вам не нужны внутренние переменные, которые будут определены до вашей первой отправки. И поскольку вы также не хотите отправлять что-либо, пока не создадите свои магазины, это станет проблемой.

Но это также означает, что диспетчер по умолчанию имеет своего рода круговую зависимость от себя (опираясь на возвращаемые значения своих собственных функций, хранящихся во внешних переменных). Но это дизайн диспетчера. Если вы не собираетесь писать нового диспетчера, это только часть сделки.

Следует также отметить, что если вы создадите истинную круговую зависимость, вызвав несколько тупиков друг против друга, диспетчер правильно выложит ошибку, говорящую столько же;

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

Вы правы, GoalStore не должен говорить SessionStore.refresh() (и emitchange), он должен сказать GoalStore.refresh(). Но мне все еще нужно, чтобы SessionStore dispatchToken смог дождаться завершения SessionStore, прежде чем GoalStore сможет обновить ... Я обновляю исходный вопрос с потоком, чтобы сделать его более понятным. –

+0

Да, это очень верно - бит ошибки новичка javascript там (не понял, что я назначал функцию). Я думаю, используя getDispatchToken() в диспетчеризации вместо того, чтобы пытаться получить его во время объявления, решит его - спасибо! –

+0

На самом деле, я беру это обратно. dispatcher.register Возвращает диспетчер отправки (https://facebook.github.io/flux/docs/dispatcher.html). Итак, что я сделал, это реализовать свой собственный getDispatchToken, вместо того, чтобы использовать его из flux utils.В любом случае, спасибо за то, что вызвали меня по правильному пути :-) –