一、场景介绍
基于vue的项目中遇到这样一个问题:在做百度地图实现车辆实时轨迹跟踪时,客户端浏览器在发送请求获取服务端数据时,由于服务端的数据量过大(数据少则几千条,多则万级计算),在将服务端轨迹数据渲染到浏览器地图上时,耗时特别大,体验特别差(数据量越大,耗时就越大,少则十几秒)。
二、问题分析
- 由于该项目实时轨迹不能使用异步加载服务端数据,因为在获取数据库中数据,开启实时之前,需要将历史数据全部有序的渲染到浏览器地图上,如果使用异步,那么在数据还没有渲染完成,就进行其他的操作,会导致实时轨迹数据经纬度和时间出现差错,同时,如果进行其他操作的话,由于加载轨迹数据和其他操作(如拖动地图,缩放查看全图等)时并列进行,导致界面处于卡顿状态、出现假死、渲染空白滞留等问题,体验也是特别差。所以此处排除异步加载数据,选择同步。
- 在获取后台数据时,当数据量越大,耗时越长,问题在于请求服务端的数据后返回的数据包过大,我们可以尽最大限度来压缩数据包,缩短数据请求和渲染时间,从而优化性能。
三、功能实现
为了解决上面的问题,我们可以先在后端对数据进行压缩处理,然后将压缩后的数据发送给前台,前台接收到的数据是压缩后的,不能直接使用,需要先解压,然后在再使用。
此处,后端使用java语言,用Gzip对数据进行压缩,前台使用pako.js对数据进行解压,具体实现方法如下:
压缩前的部分原始数据截图:

后端GZip压缩java代码:
package com.welink.biz.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; /** *字符串压缩 **/ public class StringCompress{ /**压缩字符串 * @param str:正常的需要压缩的字符串 * @return 压缩后的字符串 **/ public static String compress(String str) { if (str.length() <= 0) { return str; } try{ ByteArrayOutputStream bos = null; GZIPOutputStream os=null; //使用默认缓冲区大小创建新的输出流 byte[] bs =null; try{ bos = new ByteArrayOutputStream(); os = new GZIPOutputStream(bos); os.write(str.getBytes()); //写入输出流 os.close(); bos.close(); bs = bos.toByteArray(); return new String(bs,"ISO-8859-1"); }finally{ bs = null; bos = null; os = null; } }catch(Exception ex){ return str; } } }
压缩后的数据截图:

前台使用pako.js对数据进行解压,我们可以将pako.js直接引入到项目中。如果前端是基于vue的话,可以使用npm install pako进行安装,然后在需要使用的组件里引入即可。
前端使用Pako .js的JS解压:
const pako = require('pako'); punzipMsgSTR(str) { try { var restored = pako.ungzip(str, { to: "string" }); //解压 } catch (err) { console.log(err); } return restored; }
解压后的数据截图:

可以看出,解压后的数据是字符串形式的,而我们对数据进行处理时是需要json格式的,所以这数据不能直接拿来使用,需要将字符串数据转化成json格式的数据,所以,在此处写个函数来将字符串转换成json格式:
strToJson(str) { var json = eval("(" + str + ")"); return json; }
处理后的数据截图:

这时,数据解压完成,就可以对这个数据进行使用了。
前端完整代码如下:
punzipMsgSTR(str) { try { var restored = pako.ungzip(str, { to: "string" }); //解压 } catch (err) { console.log(err); } return restored; }, strToJson(str) { varjson=eval("("+str+")"); returnjson; }, onlive(){ let _this = this; $.ajax({ type: "post", url: "/api/biz/device/online", data: JSON.stringify({ deviceId: _this.searchText, starttime: _this.lasttime }), contentType: "application/json", async: false, success: function(res) { var data = _this.strToJson(_this.punzipMsgSTR(res)); /** *此处的data 就是已经处理过的数据,即解压过的数据,接下来就可以对该数据进行操作了。 */ } }); }
这样,从后端压缩,到前端解压就完成了,可以大大缩短数据请求和渲染时间,从而达到优化目的。此场景在现在物联网行业的使用是非常普遍的。

原创文章,作者:Ferrycoln,如若转载,请注明出处:https://ms200.cn/archives/442