CanvasJS图表渲染过慢问题:WebSocket拉取Binary数据后加载延迟如何解决
耗时成因分析
- WebSocket初始化参数错误:代码中初始化WebSocket时
lng变量还未赋值,初始值为undefined,会导致首次WebSocket连接参数异常,触发重连流程,浪费大量连接时间 - 数据请求逻辑冗余:当前逻辑是先订阅实时tick,等待收到第一个tick返回后才发起历史数据请求,额外增加了至少1次网络往返耗时,R_10品类的tick间隔为1秒,仅这一项就会导致首屏渲染延迟1秒以上
- 渲染数据堆积:每次收到历史数据时都直接往
dps数组push新数据,没有清空旧数据,随着运行时间变长dps数组会越来越大,CanvasJS渲染大数据量时耗时会显著升高 - 循环内冗余计算:遍历生成数据点时,每个节点都调用
Math.max.apply(null, spot)和Math.min.apply(null, spot)计算极值,相当于每次循环都遍历整个spot数组,总时间复杂度为O(n²),数据量大时计算耗时明显 - 重复DOM查询:
toggleDigit函数每次执行都发起DOM查询,高频调用时会增加主线程阻塞时间
性能排查方法
可以通过添加时间戳打印快速定位耗时环节:
// ws.onopen 回调内添加 console.log('连接建立完成:', Date.now()) // 收到history数据时添加 console.log('历史数据返回:', Date.now()) // chart.render() 前后各加一行 const renderStart = Date.now() chart.render() console.log('渲染耗时:', Date.now() - renderStart)
连接建立完成到历史数据返回的时间差为API请求耗时,render前后的时间差为渲染耗时。
优化方案
- 调整变量初始化顺序,先给
lng赋值再初始化WebSocket,避免无效重连:
// 调整变量赋值顺序,先赋值lng再初始化ws lng = "EN"; ws = new WebSocket("wss://ws.binaryws.com/websockets/v3?app_id=3738&l=" + lng);
- 优化数据请求逻辑,WebSocket连接打开后直接同时请求历史数据和订阅实时tick,无需等待第一个tick返回:
ws.onopen = function(evt) { ws.send(JSON.stringify({ ticks: rnd })); // 新增:直接请求历史数据,不用等tick返回 ws.send(JSON.stringify({ ticks_history: rnd, end: "latest", start: 1, style: "ticks", count: cnt + 1 })); };
- 处理历史数据前先清空
dps数组,避免旧数据堆积:
if (b.history && b.echo_req.ticks_history == rnd) { dps = []; // 新增这行清空旧数据 // 后续原有逻辑不变 }
- 预计算极值,避免循环内重复计算:
// 处理历史数据时,先算好最大最小值 const spotNumbers = spot.map(v => parseFloat(v)) const maxVal = Math.max.apply(null, spotNumbers) const minVal = Math.min.apply(null, spotNumbers) // 循环内直接用maxVal和minVal判断即可,不用每次重新计算
- 提前缓存所有digit的DOM节点,避免每次更新都重复查询:
// 初始化阶段缓存节点 const digitSpans = document.querySelectorAll("#digits > span") // toggleDigit直接用索引取节点,不用再查询 function toggleDigit(d, m) { const target = digitSpans[d-1] const nameClass = target.className; if (nameClass != "digits_moved_" + m) { target.classList.remove(nameClass); target.classList.add("digits_moved_" + m); } }
- 可选优化:关闭tooltip动画,进一步降低渲染耗时:
toolTip: { enabled: true, animationEnabled: false, // 把原配置的true改成false // 其余配置不变 }
内容的提问来源于stack exchange,提问作者Robiul
相关产品推荐
相关产品推荐

