项目场景:
实现30000+设备的全国布局图,并且设备数量仍在持续增长,如何将海量点渲染至高德地图。通过zoom等级分两个图层(地级市图层和设备图层)请求懒加载设备点,尝试减少http请求,探索开辟webworker对地级市点大小进行计算等性能优化手段。记录一下自己的实现和思考。
1.地级市图层
2.设备图层(单个地级市,如苏州市)
需求描述
1.进入全国布局页面,只渲染地级市点图层,通过deviceSize渲染点的大小。
2.点击级联组件进行搜索城市,定位到所在城市并且请求设备点数据,并且在地图上绘制出来,同时要隐藏所有的地级市点。
3.监听地级市点图层的marker点击事件,定位到该城市并且请求设备点数据,并且在地图上绘制出来,同时要隐藏所有的地级市点。
4.根据鼠标滚轮缩放地图,放大地图,监听zoomchange事件,通过zoom是否大于10来控制地级市点图层和设备点图层的显示隐藏。并且zoom在大于10的情况下才会去请求地图中心点所处的地级市的数据,并且在地图上绘制出来,同时要隐藏所有的地级市点。
优化思路:
1.总体思路,本来想直接使用vue-amap的海量点。但是此方法的缺点1仅支持h5浏览器,2在点数量10万以内有较好的性能表现,超过10万性能无法保证。
最后选择基于 Zoom 层级的懒加载,zoom以10为分界点,小于10则只展示地级市点图层;大于10则展示设备点图层。先加载地级市点,再通过地级市去加载对应的设备点,减少了很多请求。(后端返回的数据如下)
2.通过缓存到sessionStorage减少重复的http请求,请求地级市数据时一次即可拿到数据;
3.请求设备点数据不需要优化,因为是通过地址单个请求,主要减少请求的是向高德api的请求,由于后端返回的是城市名,没有返回经纬度,无法直接在地图上渲染点,需要通过高德的getLocation()获取到城市对应的经纬度,将地级市点渲染出来。流程如下:城市名=>经纬度=>渲染点。
尝试1:分批请求
可以将城市名=>经纬度分批处理,每批处理一定数量的地址,使用Promise.all
,同时控制并发数量,避免触发 API 的调用频率限制。
// 加载城市点(设备总数量)
loadCitiesMarkers() {
// 如果数据加载完成
if (this.citiesData && this.citiesData.length > 0) {
console.log('loadCitiesMarkers with citiesData', this.citiesData);
// 将请求分为若干批次
const batchSize = 6;
const promises: Promise<void>[] = [];
// 分批处理城市数据
for (let i = 0; i < this