客户端(AngularJS应用程序)从服务器获取相当大的列表。这些列表可能包含数百或数千个元素,这可能意味着几兆字节未压缩(并且一些用户(管理员)可以获得更多数据)。
我不打算让客户端得到部分结果,因为排序和过滤不应该打扰服务器。
压缩工作正常(因数大约为10),并且由于列表不经常更改,304 NOT MODIFIED
也有很大帮助。但是缺少另一个重要的优化:
由于列表的典型更改相当小(例如,修改两个元素并添加新元素),因此传输更改听起来只是一个好主意。我想知道如何正确地做到这一点。
GET
/offer/123/items
之类的内容应该始终返回商品号码123中的所有商品,对吗?这里可以使用压缩和304,但没有增量更新。像GET
/offer/123/items?since=1495765733
这样的请求听起来像是要走的路,但是浏览器缓存不会被使用:
显然,当使用“since”查询时,“资源”不会缓存任何内容(原始查询只使用一次或根本不使用)。
所以我不能依赖浏览器缓存,我只能使用localStorage
或sessionStorage
,这有一些缺点:
鉴于有HTML 5和HTTP 2.0,这是非常令人不满意的。我错过了什么?
是否可以将浏览器HTTP缓存与增量更新一起使用?
答案 0 :(得分:4)
我认为你缺少一件事:总之,标题。我认为你可以做的并且符合(大多数)你的要求的是:
GET
/offer/123/items
正常完成,没什么特别的。GET
/offer/123/items
将与Fetched-At: 1495765733
标头一起发送,表示您的服务器何时发送了初始请求。从现在开始,可能有两种情况。
Cache-Control: no-cache
。这使您可以进行增量更新,并缓存初始兆字节大小的元素。
但仍有一个缺点,即缓存只执行一次,它不会缓存更新。你说你的列表不经常更新,所以它可能已经适合你了,但是如果你真的想进一步推动它,我可以想到一件事。
收到增量更新后,您可以在后台触发另一个请求,而不会使用您的应用程序根本不会使用的Fetched-At
标头,但只会更新您的http缓存。它不应该像听起来那么糟糕,因为你的框架不会用新的数据更新它的数据(并且可能触发重新渲染),唯一值得注意的缺点是网络和内存消耗。在移动设备上它可能会有问题,但它听起来并不像是要在它们上显示的应用程序。
我绝对不知道你的用例,只会把它扔出去,但你真的确定做某种分页是行不通的吗?对于普通人来说,数兆字节的数据听起来很多;)
答案 1 :(得分:3)
我会完全放弃请求/响应周期并转移到推送模型。 具体来说, WebSockets 。
这是用于提供实时股票数据表的金融交易网站的标准技术。这是一个展示WebSockets功能的生产应用程序:
https://www.poloniex.com/exchange#btc_eth
WebSocket应用程序有两种类型的状态:全局和用户。上面的链接将显示三个全球数据表。当您登录时,底部会显示两个用户数据附加表。
这不是HTTP;你将无法将其打成Java Servlet。您需要在服务器上运行单独的进程,该进程通过TCP进行通信。好消息是,有成熟的解决方案随时可用。基于Java的解决方案具有非常好的免费许可选项,包括客户端和服务器API(并且与Angular2集成)是Lightstreamer。他们也有一个组织良好的demo page。还有适配器可用于与您的数据源集成。
您可能会犹豫是否放弃现有的servlet方法,但从长远来看,这将不那么令人头疼,并且可能会非常精彩。即使使用精心设计的仅限标头请求,HTTP轮询也不能很好地扩展到经常更新的大型列表。
---------- 编辑 ----------
由于列表更新很少,因此WebSockets可能过度。根据对此答案的评论提供的进一步细节,我建议使用基于DOM的,AJAX更新的分拣机和过滤器,例如DataTables,它有一些内置的options for caching。为了跨会话重用客户端数据,应修改上一个链接中的ajax请求,以便在每个ajax请求之后将current data in the table保存到localStorage
,并在客户端启动新会话时,使用这个数据。这将允许插件管理过滤,排序,缓存和基于浏览器的持久性。
答案 2 :(得分:2)
我正在考虑类似于Aperçu的想法,但使用了两个请求。这个想法还不完整,所以请耐心等待......
GET
/offer/123/items
,可能包含ETag
和Fetched-At
标题。服务器以
回答200
以及完整列表,如果缺少任何标头,或者自Fetched-At
时间戳304
如果此后没有任何变化304
以及一个特殊的Fetch-More
标题告诉客户端要提取更多数据最后一种情况违反了HTTP应该如何工作,但AFAIK是让浏览器缓存所有我想要它缓存的唯一方法。由于整个通信都是加密的,代理人不能因违反规范而惩罚我。
客户通过请求Fetch-Errata
GET
来回应/offer/123/items/errata
。这样,资源就分成了两个请求。分裂是丑陋的,但角度$ http拦截器可以隐藏应用程序的丑陋。
第二个请求也是可缓存的,并且还可以有Fetched-At
标头。细节尚不清楚,但一些强有力的手淫让我相信它可以奏效。实际上,勘误本身可能是不准确的,但仍然有用并且自己获得勘误......等等。
使用HTTP / 1.1,更多的请求可能意味着更多的延迟,但由于节省的带宽,其中一些请求仍然有利可图。服务器可以决定何时停止。
使用HTTP / 2,可以一次发送多个请求。可以使服务器有效地处理它们,因为它知道它们属于一起。一些更多的手淫......
我觉得这个想法很奇怪,但很有趣,我很期待发表评论。请随意给我打电话,但请留下解释。