6

我有一个使用 Facebook 的 Flux Architecture 开发的网络应用程序。该页面有两个视图:一个显示 TODO 项目列表。第二个视图显示一组随机的 TODO 项。

显然有两个问题需要由商店管理。第一个是可用 TODO 的列表。第二个是随机选择的 TODO 项列表。

因此,我有一个TODOStore,他只关心管理可用的 TODO 项目。它对loadTODOs, addTODO, deleteTODO,有动作editTODO。启动时,此存储不会加载所有 TODO 项。我希望它仅在必要时从数据库中检索 TODO 项目列表。

第二家店是RandomTODOListStore。它的职责是管理随机选择的 TODO 项。在我看来,应该通过, 使用来RandomTODOListStore访问 TODO 项。TODOStoreTODOStore.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");
    }
}

问题在于,如前所述,TODOStore启动时不会加载 TODO 项。

问题是:“如何RandomTODOListStore保证TODOStore已经检索到 TODO 项?” .

4

3 回答 3

4

提议的 Flux 实现使用一种waitFor方法来同步存储。我创建了 Reflux通过让商店能够听取其他商店的声音来更轻松地处理这个问题。该功能的效果是它将保证链中的先前存储已处理它的数据。

界面有点不同,因为 Reflux 不依赖字符串常量来识别动作,所以这里是一个示例。

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();

希望这是有道理的。

于 2014-07-31T08:54:48.883 回答
2

我认为这就是为什么 Flux 架构提到需要用这里waitFor提到的方法同步存储的原因

如果你想同步你的商店,你的 RandomTODOListStore 应该看起来像:

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

然后在您的 TodoStore 上,Constants.LOAD_RANDOM_TODO如果尚未加载待办事项列表,您可以对其做出反应并加载它们。

但是我认为这过于复杂了,你可能不应该为随机的 todos 创建另一个存储,因为这个存储(我猜)总是委托给真正的 todo 存储。改用TodoStore.getRandom()_

编辑

是的 TodoStore 不需要知道它是如何使用的。因此,当您想获得一个随机的待办事项时,您可能可以使用您使用的相同事件,例如Constants.LOAD_TODOS然后从该商店获取一个随机待办事项TodoStore.getTodos()[randomIndex]

如果两个组件同时触发事件,您可以忽略第二个事件

另一种解决方案是对RandomTODOListStore加载的事件做出反应并选择主存储的一些待办事项以将它们放入 RandomTODOListStore:

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

您可以从 Fluxxor 的 Async 示例中获得启发:对于异步数据,不仅会触发一个事件,还会触发 2 个事件(命令 + 成功/失败)

于 2014-07-21T11:43:58.090 回答
0

您的 RandomTODOListStore 需要等待 TODOStore。您可以使用此库(我的)轻松实现此目的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);
   }]

]);

现在,当您的应用启动时,您只需要调用该操作

TODOActions.load();

于 2014-07-27T22:29:54.803 回答