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

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.RecordImmutable.OrderedMap 从Immutable.js 维护我在Store 中的应用程序状态 我有一个***控制器视图组件,它从 Store 获取其状态。

类似以下内容:

function getInitialState() 
    return 
        todos: TodoStore.getAll()
    

如果内部_todos 映射为空,TodoStore.getAll 方法将通过APIUtils.getTodos() 请求从服务器检索数据。我提倡读取Store触发的数据和写入ActionCreators触发的数据。 在处理请求时,我的组件将呈现一个简单的加载微调器或类似的东西 当请求解决时,APIUtils 会根据响应状态触发TODO_LIST_RECEIVE_SUCCESSTODO_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,但很好地回答了你的问题。

【讨论】:

以上是关于通量存储中的异步数据加载的主要内容,如果未能解决你的问题,请参考以下文章

Redux 存储在调度后不更新(异步数据加载)

SwiftUI 和 CloudKit 异步数据加载

Vue.js:从 Firebase 存储中检索数据后如何异步加载模板?

Ajax在jQuery中的应用(加载异步数据请求服务器数据)

Flux:如何处理多个异步请求

如何异步加载和显示数据