Это больше похоже на то, "каково ваше мнение/исправляюсь ли я в этом?" вопрос.
Пытаясь быть как можно более строгим, понимая Flux, я пытался выяснить, где сделаны звонки XHR, обрабатываются веб-гейты/внешние раздражители, происходит маршрутизация и т.д.
Из того, что я читаю в разных статьях, интервью и просмотре примеров facebook, есть несколько способов справиться с этими вещами. После строгого потока создатели Action - это те, которые выполняют все вызовы XHR с возможностью запуска действий PENDING/SUCCESS/FAILURE до и после завершения запроса.
Другой был, исходя из facebook Ian Obermiller, все запросы READ (GET) обрабатываются непосредственно Магазинами (без участия создателя/диспетчера действий), а запросы WRITE (POST) обрабатываются создателями Action, проходящими через все действия > диспетчеp > хранить поток.
Некоторые договоренности/выводы, которые мы нарисовали/хотели бы придерживаться:
- В идеале все, что происходит в/из системы, происходит только через Actions.
- Асинхронные вызовы, выходящие/входящие в систему, будут иметь PENDING/PROGRESS (думаю, файлы загружаются)/SUCCESS/FAILURE Actions.
- Один диспетчер по всему приложению.
- Действие > Диспетчеp > Сохраненные вызовы строго синхронны, чтобы отправлять сообщения, которые не могут начать другую отправку внутри, чтобы избежать цепочки событий/действий.
- Хранилища сохраняются в представлениях (учитывая его одностраничное приложение, вы хотите иметь возможность повторно использовать данные)
Несколько вопросов, с которыми мы пришли к какому-то заключению, но я не полностью удовлетворен:
-
Если вы примете подход, в котором магазины читают, а также действия для написания писем, как вы справляетесь с ситуациями, когда несколько магазинов могут использовать данные из одного вызова XHR?
Пример: вызовы API, выпущенные TeamStore до/api/teams/{id}
, который возвращает что-то вроде:{ entities: { teams: [{ name: ..., description: ..., members: [1, 2, 4], version: ... }], users: [{ id: 1 name: ..., role: ..., version: ... }, { id: 2 name: ..., role: ..., version: ... }, { id: 3 name: ..., role: ..., version: ... }] } }
В идеале я также хотел бы обновить MemberStore с информацией, возвращаемой в этом API. Мы поддерживаем номер версии для каждого объекта, который обновляется при обновлении записи, и это то, что мы используем внутренне, отклоняем вызовы на устаревшие данные и т.д. Используя это, я мог бы иметь внутреннюю логику, где, если бы я был побочным эффектом какой-то другой вызов API, я знаю, что мои данные устарели, я запускаю обновление на этой записи.
Возможно, решение состоит в том, что вам понадобится магазин для запуска действия (которое эффективно обновит другие зависимые магазины). Это короткое замыкание в Store > View > Action to Store > Action, и я не уверен, что это хорошая идея. У нас уже есть одна вещь, которая не синхронизируется с Магазинами, которые делают свои собственные звонки XHR. Концессии, подобные этим, в конечном итоге начнут проникать во всю систему.
Или магазины, которые знают о других магазинах и могут общаться с ними. Но это ломает магазины, у которых нет правил Setters.-
Простым решением вышеупомянутой проблемы будет то, что вы будете придерживаться "Действия", являющиеся ТОЛЬКО местом, в котором происходит внешний входящий/исходящий стимул. Это упрощает логику обновления нескольких магазинов.
Но теперь, где и как вы обрабатываете кеширование? Мы пришли к выводу, что кэширование произойдет на уровне API Utils/DAO. (если вы посмотрите на диаграмму потоков).
Но это создает другие проблемы. Чтобы лучше понять/объяснить, что я имею в виду, например:-
/api/teams
возвращает список всех команд, с которыми я показываю список всех команд. -
При нажатии на ссылку команды я перехожу к его подробному представлению, для которого требуются данные из
/api/teams/{id}
, если он еще не присутствует в магазине.
Если Actions обрабатывает все XHR, View будет делать что-то вродеTeamActions.get([id])
, которое делаетTeamDAO.get([id])
. Чтобы иметь возможность немедленно вернуть этот вызов (так как мы его кэшировали), DAO придется выполнять кэширование, но также поддерживать связь между коллекциями/элементами. Эта логика, по дизайну, уже присутствует в магазинах.
Вот и вопросы: -
Вы дублируете эту логику в DAO и магазинах?
- Вы информируете DAO о Магазинах, и они могут спросить у Магазина, есть ли у них уже какие-то данные и просто вернуть сообщение 302, вы хорошо знаете последние данные.
-
-
Как вы обрабатываете проверку, которая включает в себя XHR API? Что-то простое, как дубликаты имен команд.
Представления напрямую попадают в DAO и делают что-то вродеTeamDAO.validateName([name])
, которое возвращает обещание или вы создаете действие? Если вы создаете действие, через которое Store делает действительный/недопустимый поток обратно в представление, рассматривая его в основном переходные данные? -
Как вы обрабатываете маршрутизацию? Я посмотрел через ретранслятор, и я не уверен, что мне это нравится. Я не обязательно думаю, что принудительный способ JSX реагирования на предоставление маршрутных сопоставлений/конфигов вообще необходим. Кроме того, по-видимому, в нем используется собственный RouteDispatcher, который применяется к одному правилу диспетчера.
Решение, которое я предпочитаю, было получено из некоторых сообщений в блогах /SO, где у вас есть сопоставления маршрутов, хранятся в RouteStore.
RouteStore также поддерживает CURRENT_VIEW. Реактивный компонент AppContainer регистрируется в RouteStore и заменяет его дочерние представления CURRENT_VIEW на изменение. Текущие представления сообщают AppContainer, когда они полностью загружены, и AppContainer запускает RouteActions.pending/success/failure, возможно, с некоторым контекстом, чтобы информировать другие компоненты о достижении стабильного состояния, показывать/скрывать индикаторы занятости/загрузки.
-
Что-то, что я не смог создать, было чисто, если бы вы планировали маршрутизацию, похожую на Gmail, как бы вы это сделали? Некоторые замечания Gmail о том, что я большой поклонник:
- URL-адреса не изменяются, пока страница не будет готова к загрузке. Он остается на текущем URL-адресе, пока его "Загрузка", и переходит на новый, когда загрузка завершена. Это делает так, что...
- При сбое вы не потеряете свою текущую страницу вообще. Поэтому, если вы работаете, а "Отправить" не удается, вы не потеряете свою почту (т.е. Вы не потеряете текущий стабильный вид/состояние). (они не делают этого, потому что автоматическое сохранение - это pwn, но вы получаете идею). У вас есть возможность копировать/вставлять почту где-то для безопасного хранения, пока вы не сможете отправить ее снова.
Некоторые ссылки:
https://github.com/gaearon/flux-react-router-example
http://ianobermiller.com/blog/2014/09/15/react-and-flux-interview/
https://github.com/facebook/flux