通量存储中的异步数据加载
Posted
技术标签:
【中文标题】通量存储中的异步数据加载【英文标题】:Asynchronous data loading in flux stores 【发布时间】:2014-09-01 07:27:04 【问题描述】:假设我有一个 TodoStore。 TodoStore 负责保存我的 TODO 项目。待办事项存储在数据库中。
我想知道将所有待办事项加载到商店的推荐方式是什么,以及视图应如何与商店交互以在启动时加载待办事项。
第一个替代方法是创建一个loadTodos
操作,该操作将从数据库中检索待办事项并发出一个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 项完全相同,因此不需要更新或通知视图。唯一的问题是,现在 store 已经取回了数据,所以现在缓存在 store 中。从 View 的角度来看,它不应该真正关心 Store 是如何实现的。它不应该真正关心商店是否仍然需要从数据库中检索数据。所有视图关心的是他们可以使用 Store 来获取 TODO 项,并且当创建、删除或更改新的 TODO 项时,Store 会通知他们。
因此,在这种情况下,视图应该只调用 TodoStore.getTodos() 以在加载时呈现自己,并在 TODO_CHANGE 上注册一个事件处理程序,以便在由于添加、删除或更改而需要更新自己时得到通知。
您如何看待这两种解决方案。他们还有其他解决方案吗?
【问题讨论】:
【参考方案1】:视图不必是调用 loadTodos() 的实体。这可能发生在引导文件中。
您是正确的,您应该尽力将数据流限制为调度负载内的操作。有时您需要根据其他商店的状态导出数据,这就是 Dispatcher.waitFor() 的用途。
关于您的 fetchTodoItemsFromDatabase() 解决方案的是 Flux 类似的是,没有其他实体在商店中设置数据。商店正在自我更新。这很好。
我对该解决方案的唯一严重批评是,如果您实际上是从服务器获取初始数据,它可能会导致渲染延迟。理想情况下,您将使用 html 发送一些数据。您还需要确保在控制器视图的 getInitialState() 方法中调用商店的数据。
【讨论】:
【参考方案2】:这是我对此的看法,与你的非常接近。
我通过Immutable.Record
和Immutable.OrderedMap
从Immutable.js 维护我在Store
中的应用程序状态
我有一个***控制器视图组件,它从 Store 获取其状态。
类似以下内容:
function getInitialState()
return
todos: TodoStore.getAll()
如果内部_todos
映射为空,TodoStore.getAll
方法将通过APIUtils.getTodos()
请求从服务器检索数据。我提倡读取在Store
触发的数据和写入在ActionCreators
触发的数据。
在处理请求时,我的组件将呈现一个简单的加载微调器或类似的东西
当请求解决时,APIUtils
会根据响应状态触发TODO_LIST_RECEIVE_SUCCESS
或TODO_LIVE_RECEIVE_FAIL
等操作
我的TodoStore
将通过更新其内部状态来响应这些操作(使用从操作有效负载创建的Immutable.Record
填充其内部Immutable.OrderedMap
。
如果您想通过基本实现查看示例,请查看this answer about React/Flux and xhr/routing/caching 。
【讨论】:
【参考方案3】:我知道这已经是几年前的事了,但它完美地总结了我这周遇到的问题。因此,为了帮助其他可能遇到这个问题的人,我发现 Nick Klepinger 的这篇博文对我很有帮助:"ngrx and Tour of Heroes"。
它专门使用 Angular 2 和 @ngrx/store,但很好地回答了你的问题。
【讨论】:
以上是关于通量存储中的异步数据加载的主要内容,如果未能解决你的问题,请参考以下文章
Vue.js:从 Firebase 存储中检索数据后如何异步加载模板?