一、现象
1.在使用highstock进行数据展示的时候,当数据量达到一定级别时(万以上),在IE浏览器中会产生out of memory异常;
2.当将数据量减小到2000左右时,有时会出现脚本无响应,是否关闭脚本的提示。
二、原因
1.闭包可以很轻松的在IE中产生内存泄漏,我们举两个例子来解释:
function leakMemory() { var el = document.getElementById('el'); var o = { 'el': el }; el.o = o; }
以上代码形成了javascript对象和DOM对象之间的循环引用,el和o所占用的内存空间不会被释放,直到浏览器被关闭。
function leakMemory() { var el = document.getElementById('el'); el.onclick = function() { this.style.backgroundColor = 'red'; } }
以上代码看起来非常美好,其实确实没什么问题,但是在IE中同样发生了内存泄漏。因为在内部的匿名函数所形成的闭包中调用了el的引用,同样创建了javascript对象(函数)和本地DOM对象之间的循环引用,它们产生的内存同样不会被释放。
当数据量达到一定级别时,内存泄漏便会被暴漏出来。
2.我们参考官网的例子,发现52000个点都没有出现脚本无响应异常,经debug发现,在初始化渲染图表时,其所选择的范围不是全部,而是一部分,这样一开始只加载了很少一部分点,因此没有出现脚本无响应异常。
三、解决方案:
采用动态获取数据的方式,每次查询和选择一段时间都会向后台发送请求来获取数据,在后台保证每次传递给前台的数据量不超过限制。
实现步骤:
1.在x轴的配置中设置afterSetExtremes事件:
xAxis : { events : { afterSetExtremes : afterSetExtremes }, type: 'datetime', dateTimeLabelFormats: { hour: '%Y-%m-%d<br/>%H:%M', day: '%Y<br/>%m-%d', week: '%Y<br/>%m-%d', month: '%Y-%m', year: '%Y' }, minRange: 3600 * 1000 // one hour },
/** * Load new data depending on the selected min and max */ function afterSetExtremes(e) { //获取截取的时间段 var startTime = new Date(); startTime.setTime(Math.round(e.min)); var endTime = new Date(); endTime.setTime(Math.round(e.max)); chart.showLoading('@Tip.loading@'); $.getJSON(url, function(json) { chart.hideLoading(); //给每个线重新赋值 var series = chart.series; $.each(series,function(index, serie){ if(serie.name!="Navigator"){ var key = serie.userOptions.key; serie.setData(json[key], false);//第二个参数设置为false表示不会在每个点加载后都重新渲染 } }); chart.redraw(); }); }
2.一定不能忘掉需要配置如下选项,才能保证上述配置生效:
navigator : { adaptToUpdatedData: false },
3.在后台每次查询到真实的完整数据后,根据个数来决定需要隔多少个点进行采样,并且记住加上第一个点和最后一个点,放在生成的图表首尾缺失。