ECharts 大屏内存泄漏排查与治理
一、问题背景
在可视化大屏项目中,页面通常需要部署到客户现场长期运行,很多场景都是 7 x 24 小时持续展示。
实际项目中遇到过这样的问题:
- 页面运行几天后出现卡顿
- 内存占用持续升高
- 最终浏览器崩溃,导致大屏不可用
如果页面中图表数量较多,并且存在动态刷新需求,就需要重点排查 ECharts 是否引发了内存泄漏问题。
二、常见原因
1. 重复创建图表实例
在动态更新图表时,如果每次都调用 echarts.init() 创建新实例,而不是复用旧实例,就会导致实例不断累积,内存持续增长。
2. 事件监听没有解绑
每个图表都可能绑定点击、悬浮、缩放等事件。如果组件销毁时没有正确调用 off() 解绑,就会残留监听器,导致无法被垃圾回收。
3. 定时器没有清理
很多大屏会使用定时器轮询或定时刷新图表。如果组件卸载时没有及时 clearInterval() 或 clearTimeout(),就可能持续触发更新逻辑,间接造成内存泄漏。
三、真实问题定位
排查后发现,项目中主要问题是:
- 定时刷新数据时重复执行
echarts.init() - 销毁阶段
clear和dispose使用不当 - 事件解绑和定时器清理不完整
最终导致:
- 定时器不断触发重绘
- ECharts 实例越来越多
- 浏览器内存持续上升,最终崩溃
四、clear() 和 dispose() 的区别
1. clear()
作用:
- 清空当前图表配置和数据
- 保留 ECharts 实例本身
适用场景:
- 需要保留实例,只是重新绘制内容
- 使用同一个实例反复更新数据
特点:
- 不会释放实例占用的核心内存
- 不需要重新
init
2. dispose()
作用:
- 彻底销毁 ECharts 实例
- 释放 DOM 引用、事件监听和内部资源
适用场景:
- 图表生命周期结束
- DOM 被销毁或组件即将卸载
特点:
- 会真正释放内存
- 后续如果还要绘制,需要重新执行
echarts.init()
五、正确治理方案
1. 优先复用实例
推荐在初始化前先判断当前 DOM 上是否已经存在实例:
- 如果有实例,直接使用
setOption()更新数据 - 如果没有实例,再调用
echarts.init()
2. 销毁阶段彻底清理资源
在组件销毁前统一处理:
- 调用
chart.off()解绑事件 - 调用
chart.dispose()销毁实例 - 调用
clearInterval()或clearTimeout()清理定时器
3. 避免无意义重绘
在动态更新场景中,尽量:
- 复用实例
- 只更新变化的数据
- 控制刷新频率
六、可以这样向面试官表述
1. 现象
客户现场的大屏运行几天后页面崩溃,本地短时间压测不容易复现。
2. 排查过程
- 使用 Chrome DevTools 观察内存变化
- 发现内存随时间持续增长且没有回落
- 结合代码排查,定位到定时刷新逻辑中重复执行
echarts.init() - 同时发现事件监听未解绑、定时器未清理的问题
3. 解决方案
- 使用
getInstanceByDom()获取并复用实例 - 动态更新时统一使用
setOption() - 组件销毁时调用
dispose()、解绑事件并清理定时器
4. 结果
- 大屏长时间运行内存保持稳定
- 页面卡顿和崩溃问题被解决
- 项目可以稳定支撑长期在线展示
七、适合写进简历的亮点
简历表达示例:
负责排查并治理 ECharts 大屏内存泄漏问题,定位定时刷新中重复
echarts.init()、事件未解绑、定时器未清理等隐患;通过实例复用、正确销毁和刷新策略优化,保障大屏 7 x 24 小时稳定运行。
