javascript - Upravljanje ovisnostima podataka trgovine u React/Fluxu
Imam web aplikaciju razvijenu koristeći Facebookovu Flux arhitekturu. Stranica ima dva prikaza: jedan prikazuje popis TODO stavki. Drugi prikaz prikazuje slučajni skup TODO stavki.
Jasno postoje dvije brige koje trgovine trebaju upravljati. Prva je popis dostupnih TODO stavki. Druga je popis nasumično odabranih TODO stavki.
Dakle, imam TODOStore, čija je briga isključivo upravljanje dostupnim TODO stavkama. Ima akcije za loadTODOs, addTODO, deleteTODO, editTODO. Pri pokretanju, ovaj store ne učitava sve TODO stavke. Želim da dohvaća popis TODO stavki iz baze podataka samo kada je potrebno.
Druga trgovina je RandomTODOListStore. Njena je odgovornost upravljati nasumično odabranim TODO stavkama. Čini mi se da bi RandomTODOListStore trebala pristupati TODO stavkama putem TODOStore, koristeći 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 s ovim je što, kao što je prethodno navedeno, TODOStore ne učitava TODO stavke prilikom pokretanja.
Pitanje je: "Kako RandomTODOListStore jamči da je TODOStore već dohvatila TODO stavke?".
Odgovor #1
Predložena Flux implementacija koristi waitFor metodu za sinkronizaciju spremišta. Stvorio sam Reflux kako bih to mnogo jednostavnije riješio dopuštajući spremištima da mogu slušati druga spremišta. Učinak te značajke je da će garantirati da je prethodno spremište u lancu obradilo svoje podatke.
Sučelje je malo drugačije, jer Reflux ne oslanja se na nizove konstanti da bi razlikovao akcije, pa evo jednog primjera.
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();
Nadam se da ovo ima smisla.
Odgovor #2
Mislim da je ovo razlog zašto arhitektura Flux spominje potrebu za sinkronizacijom trgovina s metodom waitFor spomenutom ovdje
Ako želite sinkronizirati svoje trgovine, vaš RandomTODOListStore vjerojatno bi trebao izgledati ovako:
case Constants.LOAD_RANDOM_TODO:
Dispatcher.waitFor([TodoStore.dispatcherIndex],this.loadRandomTODO);
break;
Zatim na svom TodoStoreu možete reagirati na Constants.LOAD_RANDOM_TODO i učitati popis zadataka ako još nisu učitani.
Međutim, mislim da je ovo prenapredno, i vjerojatno ne biste trebali stvarati još jednu pohranu za nasumične zadatke jer će ova pohrana (pretpostavljam) uvijek delegirati pravoj pohrani zadataka. Samo koristite TodoStore.getRandom() umjesto toga
Uredi:
Da, TodoStore ne treba znati kako se koristi. Dakle, kada želite dobiti nasumični todo, vjerojatno možete koristiti isti događaj koji koristite, kao Constants.LOAD_TODOS, a zatim dobiti nasumični todo iz tog spremišta pomoću TodoStore.getTodos()[randomIndex]
Ako oba sastavna dijela istovremeno pokrenu događaj, možete zanemariti drugi događaj
Drugo rješenje je da RandomTODOListStore reagira na događaj učitavanja i odabere neke zadatke iz glavne pohrane kako bi ih stavio u RandomTODOListStore:
case Constants.TODOS_LOADED:
this.randomTodos = randomSubset(TodoStore.getTodos,subsetSize);
break;
Možete se inspirirati Async primjerom iz Fluxxora: za asinkrone podatke ne pokreće se samo jedan događaj nego dva (naredba + uspjeh/neuspjeh)
