简体   繁体   English

如何将Redux与非常大的数据集和IndexedDB集成

[英]How to integrate Redux with very large data-sets and IndexedDB

I have an app that uses a sync API to get its data, and requires to store all the data locally. 我有一个使用同步API来获取其数据的应用程序,并且需要在本地存储所有数据。 The data set itself is very large, and I am reluctant to store it in memory, since it can contains thousands of records. 数据集本身非常大,我不愿意将它存储在内存中,因为它可以包含数千条记录。 Since I don't think the actual data structure is relevant, let's assume I am building an email client that needs to be accessible offline, and that I want my storage mechanism to be IndexedDB (which is async). 由于我不认为实际的数据结构是相关的,我们假设我正在构建一个需要离线访问的电子邮件客户端,并且我希望我的存储机制是IndexedDB(它是异步的)。

I know that a simple solution would be to not have the data structure as part of my state object and only populate the state with the required data (eg - store email content on state when EMAIL_OPEN action is triggered). 我知道一个简单的解决方案是不将数据结构作为我的状态对象的一部分,并且仅使用所需数据填充状态(例如,当触发EMAIL_OPEN操作时将电子邮件内容存储在状态中)。 This is quite simple, especially with redux-thunk. 这很简单,特别是对于redux-thunk。

However, this would mean I need to compromise 2 things: 但是,这意味着我需要妥协两件事:

  1. The user data is no longer part of the "application state", although in truth it is. 用户数据不再是“应用程序状态”的一部分,尽管事实确实如此。 Since the sync behavior is complex, and removing it from the app state machine will hurt the elegance of the redux concepts (the way I understand them) 由于同步行为很复杂,将其从app状态机中删除会损害redux概念的优雅(我理解它们的方式)
  2. I really like the redux architecture and would like all of my logic to go through it, not just the view state. 我非常喜欢redux架构,并希望我的所有逻辑都能通过它,而不仅仅是视图状态。

Are there any best-practices on how to use redux with a not-in-memory state properties? 有关如何将redux与非内存状态属性一起使用的最佳实践吗? The thing I find hardest to wrap my head around is that redux relies on synchronous APIs, and so I cannot replace my state object with an async state object (unless I remove redux completely and replace it with my own, async implementation and connector). 我发现最难解决的问题是redux依赖于同步API,因此我无法用异步状态对象替换我的状态对象(除非我完全删除redux并将其替换为我自己的异步实现和连接器)。

I couldn't find an answer using Google, but if there are already good resources on the subject I would love to be pointed out as well. 我找不到使用谷歌的答案,但如果已经有很好的资源,我也很乐意指出。

UPDATE: Question was answered but wanted to give a better explantation into how I implemented it, in case someone runs into it: 更新:问题得到了回答,但想要更好地解释我是如何实现它的,以防有人遇到它:

The main idea is to maintain change lists of both client and server using simply redux reducers, and use a connector to listen to these change lists to update IDB, and also to update the server with client changes: 主要思想是使用简单的redux reducer维护客户端和服务器的更改列表,并使用连接器监听这些更改列表以更新IDB,并使用客户端更改来更新服务器:

  1. When client makes changes, use reducers to update client change list. 客户端进行更改时,使用reducers更新客户端更改列表。
  2. When server sends updates, use reducers to update server change list. 当服务器发送更新时,使用reducers更新服务器更改列表。
  3. A connector listens to store, and on state change updates IDB. 连接器侦听存储,并在状态更改时更新IDB。 Also maintain internal list of items that were modified. 还维护已修改的项目的内部列表。
  4. When updating the server, use list of modified items to pull delta from IDB and send to server. 更新服务器时,使用已修改项目列表从IDB中提取增量并发送到服务器。
  5. When accessing the data, use normal actions to pull from IDB (eg using redux-thunk) 访问数据时,使用正常操作从IDB中提取(例如使用redux-thunk)

The only caveat with this approach is that since the real state is stored in IDB, so we do lose some of the value of having one state object (and also harder to rewind/fast-forward state) 这种方法唯一需要注意的是,由于真实状态存储在IDB中,因此我们确实失去了拥有一个状态对象的一些价值(并且更难以倒带/快进状态)

I think your first hunch is correct. 我认为你的第一次预感是正确的。 If(!) you can't store everything in the store, you have to store less in the store. 如果(!)您无法将所有商品存储在商店中,则必须在商店中存储更少的商品。 But I believe I can make that solution sound much better: 但我相信我可以让这个解决方案听起来更好:

IndexedDB just becomes another endpoint, much like any server API you consume. IndexedDB只是成为另一个端点,就像您使用的任何服务器API一样。 When you fetch data from the server, you forward it to IndexedDB, from where your store is then populated. 从服务器获取数据时,将其转发到IndexedDB,然后从中填充商店。 The store gets just what it needs and caches it as long as it doesn't get too big or stale. 只要它不会变得太大或陈旧,商店就可以获得它所需要的东西并进行缓存。

It's really not different than, say, Facebook consuming their API. 这与Facebook消费他们的API并没有什么不同。 There's never all the data for a user in the store. 商店里的用户永远不会有所有数据。 References are implemented with IDs and these are loaded when required. 引用使用ID实现,并在需要时加载。

You can keep all your logic in redux. 您可以将所有逻辑保留在redux中。 Just create actions as usual for user actions and data changes, get the data you need and process it. 只需像往常一样为用户操作和数据更改创建操作,获取所需的数据并进行处理。 The interface is still completely defined by the user data because you always have the information in the store that is needed to GET TO the rest of it when needed. 该界面仍然完全由用户数据定义,因为您始终拥有商店中需要的信息,以便在需要时获取其余部分。 It's just somewhat condensed, ie you only save the total number of messages or the IDs of a mailbox until the user navigates to it. 它只是有点浓缩,即您只保存邮件的总数或邮箱的ID,直到用户导航到它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM