磁通存储中的异步数据加载

时间:2014-07-10 19:26:53

标签: flux reactjs-flux

说我有TodoStore。 TodoStore负责保存我的TODO物品。 Todo项目存储在数据库中。

我想知道将所有待办事项加载到商店的建议方式是什么,以及视图应如何与商店交互以在启动时加载TODO项目。

第一种方法是创建一个loadTodos动作,它将从数据库中检索Todos并发出TODOS_LOADED事件。然后,视图将调用loadTodos操作,然后收听TODOS_LOADED事件,然后通过调用TodoStore.getTodos()进行更新。

另一种选择是没有loadTodos操作,并且TodoStore.getTodos()将返回与现有TODO项目的承诺。如果TodoStore已经加载了TODO项目,它只返回它们;如果没有,那么它将从数据库中查询并返回检索到的项目。在这种情况下,即使商店现在已经加载了TODO项目,它也不会发出TODOS_LOADED事件,因为getTodos不是一个动作。

function getTodos() {
   if (loaded)
      return Promise.resolve($todoItems);
   else
      return fetchTodoItemsFromDatabase().then(todoItems) {
         loaded = true;
         $todoItems = todoItems;
         return $todoItems;
      });
}

我确信很多人会说这会打破Flux架构,因为getTodos函数正在改变存储状态,只有通过调度程序发送的操作才能更改存储状态。

但是,如果您认为TodoStore的状态是数据库中现有的TODO项目,那么getTodos并不是真正改变任何状态。 TODO项目完全相同,因此不需要更新或通知视图。唯一的事情是,现在商店已经检索了数据,因此它现在缓存在商店中。从View的角度来看,它不应该真正关心Store的实现方式。如果商店仍然需要从数据库中检索数据,它应该不在乎。所有关注的观点都是他们可以使用Store来获取TODO项目,并且Store会在创建,删除或更改新TODO项目时通知他们。

因此,在这种情况下,视图应该只调用TodoStore.getTodos()来加载自己,并在TODO_CHANGE上注册一个事件处理程序,以便在需要由于添加,删除或更改而自行更新时得到通知。

您如何看待这两种解决方案?他们是否有其他解决方案?

3 个答案:

答案 0 :(得分:3)

视图不必是调用loadTodos()的实体。这可能发生在引导程序文件中。

您确定应该尽量将数据流限制为调度有效负载内的操作。有时您需要根据其他商店的状态派生数据,这就是Dispatcher.waitFor()的用途。

与fetchTodoItemsFromDatabase()解决方案类似的Flux是没有其他实体在商店中设置数据。商店正在更新。这很好。

我对此解决方案的唯一严重批评是,如果您实际从服务器获取初始数据,则可能导致渲染延迟。理想情况下,您将使用HTML发送一些数据。您还需要确保要求商店'控制器视图中的数据' getInitialState()方法。

答案 1 :(得分:0)

以下是我对此的看法,非常接近你的。

  • 我通过StoreImmutable.RecordImmutable.js
  • Immutable.OrderedMap维护我的申请状态
  • 我有一个顶级控制器视图组件,可从商店获取其状态。

以下内容:

function getInitialState() {
    return {
        todos: TodoStore.getAll()
    }
}
    如果内部TodoStore.getAll地图为空,
  • APIUtils.getTodos()方法将通过_todos请求从服务器检索数据。我主张在Store中触发的读取数据和ActionCreators中触发的写入数据。
  • 在处理请求时,我的组件将呈现一个简单的加载微调器或类似的东西
  • 请求结算后,APIUtils会触发TODO_LIST_RECEIVE_SUCCESSTODO_LIVE_RECEIVE_FAIL等操作,具体取决于回复状态
  • 我的TodoStore将通过更新其内部状态(使用从操作有效负载创建的Immutable.OrderedMap填充其内部Immutable.Record来响应这些操作。

如果您想通过基本实现查看示例,请查看this answer about React/Flux and xhr/routing/caching

答案 2 :(得分:0)

我知道自问这个问题已有几年了,但它完美地总结了我本周要努力解决的问题。所以为了帮助任何可能遇到这个问题的人,我发现这篇博文真的帮助了Nick Klepinger:"ngrx and Tour of Heroes"

它专门使用Angular 2和@ ngrx / store,但很好地回答了你的问题。