客户端(一个 AngularJS 应用程序)从服务器获取相当大的列表。这些列表可能有数百或数千个元素,这可能意味着几兆字节未压缩(并且一些用户(管理员)获得更多数据)。
我不打算让客户端获得部分结果,因为排序和过滤不应该打扰服务器。
压缩效果很好(大约 10 倍)并且由于列表不经常更改,304 NOT MODIFIED
也有很大帮助。但是缺少另一个重要的优化:
由于列表的典型更改相当小(例如,修改两个元素并添加一个新元素),因此仅转移更改听起来是个好主意。我想知道如何正确地做到这一点。
像 GET
/offer/123/items
这样的东西应该总是返返回价编号 123 中的所有项目,对吗?这里可以使用压缩和304,但是不能增量更新。像 GET
/offer/123/items?since=1495765733
这样的请求听起来像是要走的路,但是浏览器缓存不会被使用:
- 要么什么都没有改变,答案是空的(并且缓存它没有意义)
- 或者某些东西发生了变化,客户端更新了它的状态,并且从 1495765733 之后就不再请求更改(缓存它就更没有意义了)
显然,当使用“since”查询时,不会为“资源”缓存任何内容(原始查询只使用一次或根本不使用)。
所以我不能依赖浏览器缓存,只能使用 localStorage
或 sessionStorage
,它们有一些缺点:
- 限制为几兆字节(浏览器 HTTP 缓存可能更大并自动处理)
- 当我达到极限时,我必须实现一些替换策略
- 浏览器缓存存储了我没有得到的已压缩数据(我必须重新压缩它们)
- 它不适用于用户(管理员)获得更大的列表,因为即使是单个列表也可能已经超过限制
- 它在注销时被清空(客户的要求)
考虑到存在 HTML 5 和 HTTP 2.0,这并不令人满意。我错过了什么?
是否可以将浏览器 HTTP 缓存与增量更新一起使用?
最佳答案
我认为您缺少一件事:简而言之,标题。我认为您可以做的并且符合您的(大部分)要求的是:
- 首先
GET
/offer/123/items
正常完成,没有什么特别的。 - 后续
GET
/offer/123/items
将与Fetched-At: 1495765733
header 一起发送,表明您的服务器在初始时请求已发送。
从现在开始,有两种可能的情况。
- 要么没有变化,你可以发送304。
- 但是,如果有变化,则返回新项目,因为之前发送的时间戳有 header ,但要在您的响应中设置
Cache-Control: no-cache
。
这使您可以进行增量更新,并缓存初始的兆字节大小的元素。
不过还有一个缺点,即缓存只进行一次,它不会缓存更新。你说你的列表不经常更新,所以它可能已经适合你了,但如果你真的想进一步插入这一点,我还能想到一件事。
收到增量更新后,您可以在后台触发另一个不带 Fetched-At
header 的请求,您的应用程序根本不会使用该 header ,但只会在那里更新您的http缓存。它在性能方面应该没有听起来那么糟糕,因为您的框架不会使用新数据更新其数据(并可能触发重新渲染),唯一值得注意的缺点是网络和内存消耗。在移动设备上它可能会出现问题,但它听起来不像是一个旨在显示在移动设备上的应用程序。
我完全不知道你的用例,只是把它扔在那里,但你真的确定做某种分页是行不通的吗?对于普通人来说,要显示和处理数兆字节的数据听起来很多;)
关于ajax - 使用浏览器缓存的增量更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44192963/