优化巨大的 JSON 响应
Posted
技术标签:
【中文标题】优化巨大的 JSON 响应【英文标题】:Optimize Huge JSON response 【发布时间】:2015-01-07 21:50:52 【问题描述】:我正在开发一个大数据客户端应用程序。服务器语言是 Java。在前端,我有大量的原生 javascript,但 AngularJS 作为 MVC 框架。
问题
处理大数据分析,一次单个 REST api 响应约为 1.5MB 到 3MB。处理这些数据来构建 DOM 是一件很痛苦的事情。
首先加载 JSON 大约需要 5 到 10 秒。 然后我构建 UI (DOM) 构建 DOM 后,基于用户与数据的交互 - 我必须使用更新值的相同 JSON 发送/返回服务器。建议,我有哪些选项可以优化页面响应能力?
我想到的几件事: 一次将 JSON 分解为 1000 个块,一旦加载 DOM,然后静默获取数据并更新 UI。 在服务器上对 JSON 进行 GZIP 压缩并在客户端解码回。给我你的具体解决方法!
示例 JSON 可能是:
var data = [
prop:val,
prop2: ,
prop3:[
id: val,
prop4: , , , ,
prop5: [ [], [], [] ]
]
,
,
,
]
一些用例
数据大小可以是 10000 个对象,嵌套在至少六、七个深度级别。 需要构建网格(表格),行的长度与对象和列的长度相同,至少 100 列。 所有数据单元格都有自定义上下文菜单、嵌套标题、所有列可排序、行可排序,一旦用户更改,这些排序的顺序就会到达服务器。但我确实有一秒的门槛。一个非常基本的例子在这里:http://shekhardesigner.github.io/OuchGrid/
【问题讨论】:
嗨,我不知道你的设计,但是延迟加载呢?也许您正在显示一个大数据列表,并且您只能加载列表的那部分,即用户可见的部分。 Here 是指向 ngInfiniteScroll 的链接 - 正是我所说的。 能否请您发布您发送给客户的数据样本。 您应该将服务器配置为 gzip 响应 - 特别是对于较慢的 Internet 连接,压缩/解压缩所需的时间应该少于下载如此大文件所需的时间。请记住,如果您设置正确的 HTTP 标头,大多数浏览器都能够本机处理压缩响应。 数据是保密的,所以我不能发布。 我只需要一个结构而不是数据本身。假装哈哈 【参考方案1】:对于我的一项任务,我们使用了自己的解决方案。大多数数据将是集合或数组,因此我们实现了简单的算法来删除所有冗余属性名称和一组属性名称和值对象的集合。我们看到了大小的显着减小,并且可能在下一个级别上,一些库可能会被用于进一步解压缩。同样,这仅在我们处理结构化数据时才有效,如果数组对象具有不同的结构,则可能需要不同的算法。
像我推荐的其他算法,看看自然压缩技术,例如从 JSON 中删除所有空格,使字段名称更小。
或者,您可以查看像 Protocol Buffers 这样的规范,它可能会产生更小的上传大小。看https://github.com/dcodeIO/ProtoBuf.js
如果处理您的数据需要时间并冻结屏幕渲染,您可以尝试使用 Web Worker(适用于最新浏览器)来卸载处理逻辑,并且主线程/事件循环仍可用于 UI 渲染或响应用户操作。
【讨论】:
我正在使用 Web Worker。协议缓冲区和其他压缩将是架构师级别的更改,所以稍后一点。 嗨,您如何使用 Web Workers 实现?【参考方案2】:“首先加载 JSON 大约需要 5 到 10 秒。然后我构建 UI (DOM)”
我建议您异步加载 UI 和数据,但在加载适当的数据之前不允许用户执行某些操作。
将数据加载到您的变量/服务中后,使用前端分页来最大程度地减少浏览器的压力。 javascript 可以存储大量数据,但 DOM 将难以呈现大量 html。
【讨论】:
【参考方案3】:我的一些建议:
-
首先对来自服务器端的响应数据进行分页以减小 json 对象的大小。
并行渲染,然后逐块渲染 ui
如果数据太大,不要对数据进行深度观察,例如不要对太多数据进行ngRepeat,如果不需要双向绑定。这将使您的应用程序非常缓慢
【讨论】:
我已经完成了所有可能的 Angular 优化,例如避免嵌套 ngRepeat、执行 bindonce、使用 trackby、构建自定义指令以使用谨慎的拦截器进行处理。 单个 REST api 响应大约 1.5MB 到 3MB 没有意义,您是否从服务器端对数据进行分页?或者你从客户端进行分页 尚未在服务器中实现分页 - 这个选项是我接下来要做的。客户端分页不是必需的,因此延迟加载也是我接下来要考虑的,但要考虑响应性。 是的,服务器端的分页至关重要。如果数据是静态的,也就是不可变的,那么考虑使用模板直接渲染html【参考方案4】:“首先加载 JSON 大约需要 5 到 10 秒。 然后我构建 UI (DOM)"
这两个步骤不能异步执行吗?例如加载 dom 并等待 ajax 回调?
我不确定是否有办法,因为我缺乏详细信息,但也许您想重新考虑在需要时加载“较小对象”的整个过程。
考虑以某种方式压缩对象/字符串
这是我现在能想到的前 3 种优化方法。根据您的用例,您也许可以添加这些建议
我希望这会有所帮助 - 随时添加反馈
【讨论】:
保持两个操作同步是一个问题,原因有两个:1.) 一旦用户看到 UI - 开始与它交互,我必须发回更新。 2.) 收到数据后立即更新 DOM 是瓶颈,因为这里的响应非常大。我一次谈论 10000+ 行,假设最少 100 列。如果我不断更新 DOM - 浏览器会冻结。 FYA,它是一个分析应用程序。 浏览器冻结意味着您使用所有这些更新向您的堆栈发送垃圾邮件......您没有给渲染队列足够的时间来重新渲染页面 -> 冻结。您可以通过将您的 DOM 更改 1 比 1 放入队列中来进行 DOM 更新 asnyc .. 这允许渲染队列“在中间渲染”并且看起来更流畅...虽然不确定这是否适用于您 如果你想批量更新你的 dom.. 只需设置一个 setTimeout(update, 0); /*update 是您的 dom-update 函数*/ 并将其推送到您的队列中...用户将应用 DOM 更改,因为他仍然能够交互,因为渲染队列可以在您之间推送其渲染 update( ) 调用 100 列? u 同时显示所有 100 列? 当您从服务器获得所有数据时 - 在客户端只需考虑将“小部分”推送到队列中,它会比等待更新所有内容要好得多;D以上是关于优化巨大的 JSON 响应的主要内容,如果未能解决你的问题,请参考以下文章