2014-07-13 6 views
5

Mam aplikację internetową opracowaną przy użyciu architektury Flux Facebooka. Strona ma dwa widoki: jeden wyświetla listę elementów TODO. Drugi widok wyświetla losowy zestaw elementów TODO.Zarządzanie zależnościami danych sklepu w React/Flux

Istnieją wyraźnie dwie kwestie, które muszą być zarządzane przez sklepy. Pierwszy to lista dostępnych TODO. Druga to lista losowo wybranych elementów TODO.

Mam zatem TODOStore, którego przedmiotem jest wyłącznie zarządzanie dostępnymi pozycjami TODO. Ma akcje do loadTODOs, addTODO, , deleteTODO, editTODO. Podczas uruchamiania ten sklep nie ładuje wszystkich elementów TODO. Chcę, aby pobierał listę elementów TODO z bazy danych tylko w razie potrzeby.

Drugi sklep to RandomTODOListStore. Odpowiedzialnością jest zarządzanie losowo wybranymi przedmiotami TODO. Wydaje mi się, że RandomTODOListStore powinien uzyskać dostęp do elementów TODO za pośrednictwem TODOStore, używając TODOStore.getTODOItems().

function RandomTODOListStore() { 
    var $randomTODOs = []; 

    dispatcher.register(function(payload) { 
     var action = payload.action; 

     switch (action.actionType) { 
      case Constants.LOAD_RANDOM_TODO: 
       loadRandomTODO(); 
       break; 
     } 
    }); 

    function loadRandomTODO() { 
     $randomTODOs = selectRandom(TODOStore.getTODOList()); 
     emit("change"); 
    } 
} 

Problem polega na tym, że, jak wcześniej wspomniano, TODOStore nie ładuje elementy TODO na starcie.

Pytanie brzmi: "W jaki sposób RandomTODOListStore gwarantuje, że TODOStore już odebrał elementy TODO?".

Odpowiedz

2

myślę, że to jest dlaczego Flux architektura wspomnieć trzeba zsynchronizować sklepów metodą waitFor mentionned here

Jeśli chcesz zsynchronizować sklepów, Twój RandomTODOListStore prawdopodobnie powinien wyglądać następująco:

case Constants.LOAD_RANDOM_TODO: 
    Dispatcher.waitFor([TodoStore.dispatcherIndex],this.loadRandomTODO); 
    break; 

Następnie na swoim TodoStore, możesz zareagować na Constants.LOAD_RANDOM_TODO i załadować listę todos, jeśli nie są jeszcze załadowane.

Jednak myślę, że jest to zbyt skomplikowane i prawdopodobnie nie powinieneś tworzyć kolejnego sklepu dla losowych todos, ponieważ ten sklep będzie (jak sądzę) zawsze delegował do prawdziwego sklepu todo. Wystarczy użyć TodoStore.getRandom() zamiast

Edit:

Tak TodoStore nie musi wiedzieć, w jaki sposób jest ona wykorzystywana. Tak więc, jeśli chcesz dostać losowy todo, prawdopodobnie można użyć tego samego zdarzenia w użyciu, jak Constants.LOAD_TODOS a następnie dostać losowy todo z tego sklepu z TodoStore.getTodos()[randomIndex]

Jeśli oba elementy ognia zdarzenie jednocześnie, można zignorować 2nd impreza

Innym rozwiązaniem jest mieć RandomTODOListStore reagować na załadowanej zdarzenia i wybrać kilka todos głównego sklepu, aby umieścić je w RandomTODOListStore:

case Constants.TODOS_LOADED: 
    this.randomTodos = randomSubset(TodoStore.getTodos,subsetSize); 
    break; 

Możesz inspirować się z Async exemple from Fluxxor: dla danych asynchroniczny , nie ma tylko jednego zdarzenie, które zostało uruchomione, ale 2 (polecenie + sukces/niepowodzenie)

+0

Tak, pomyślałem o tym. Problem polega na tym, że TODOStore nie powinien przejmować się tym, jak inni go używają. Nie powinno reagować na działania RandomTODOListStore. Wyobraź sobie, że za każdym razem, gdy mam coś innego, co wymaga pozycji TODO, TODOStore bardzo szybko się rozdęci. – rafalotufo

+0

@rafalotufo zobacz moją edycję –

0

Twój RandomTODOListStore musi poczekać na TODOStore.Można to łatwo osiągnąć za pomocą tej biblioteki (kopalnia) https://github.com/kjda/ReactFlux

var ReactFlux = require('react-flux'); 

var TODOConstants = ReactFlux.createConstants(['LOAD'], 'TODO'); 

var TODOActions = ReactFlux.createActions({ 
    load: [TODOConstants.TODO_LOAD, function(){ 
     //load your todos here 
     return { todos: [{title: 'do this'}, {title: 'do that'}]} 
    }] 
}); 

var TODOStore = ReactFlux.createStore({ 
    getTodos: function(){ 
     return this.getState().todos; 
    } 
}, [ 
    [TODOConstants.TODO_LOAD_SUCCESS, function(payload){ 
     this.setState({ 
      todos: payload.todos 
     }); 
    }] 
]); 

var RandomTODOListStore = ReactFlux.createStore({ 
    selectRandomFromList: function(todos){ 
     //..... select some here 
    } 
}, [ 

    /** 
    * This waits for TODOStore to process the message first 
    */ 
    [TODOConstants.TODO_LOAD_SUCCESS, [TODOStore], function(payload){ 
     this.selectRandomFromList(payload.todos); 
    }] 

]); 

teraz gdy aplikacja rozpoczyna wystarczy zadzwonić działaniem

TODOActions.load();

4

Proponowana implementacja Flux wykorzystuje metodę waitFor do synchronizowania sklepów. Stworzyłem Reflux, aby poradzić sobie z tym znacznie łatwiej, pozwalając sklepom na słuchanie innych sklepów. Efektem tej funkcji jest to, że zagwarantuje to, że poprzedni sklep w łańcuchu obsługiwał dane.

Interfejs jest nieco inny, ponieważ Reflux nie polega na stałych łańcuchowych, aby odróżnić akcje, więc tutaj jest przykład.

var TodoActions = Reflux.createActions(['load']); 

var todoStore = Reflux.createStore({ 
    init: function() { 
     // Listen to the load action 
     this.listenTo(TodoActions.load, this.loadActions); 
    }, 
    loadActions: functions() { 
     var loadedActions = []; 
     // load your actions into loadedActions 
     // and do then the following inside the ajax 
     // callback when it is done: 
     this.trigger(loadedActions); 
    } 
}); 

var randomTodoStore = Reflux.createStore({ 
    init: function() { 
     // You may listen to stores as well 
     this.listenTo(todoStore, onLoadedActions); 
    }, 
    onLoadedActions: function(loadedActions) { 
     // loaded actions will be passed in from the 
     // dotoStores change event trigger 

     // you may do your select random from loaded 
     // actions list 
    } 
}); 

// Invoke the action 
TodoActions.load(); 

Mam nadzieję, że to ma sens.