You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TeeChart for JavaScript大数据量处理报错及承载能力咨询

解决TeeChart for JavaScript处理大量数据时的栈溢出问题

首先可以明确:TeeChart for JavaScript完全可以处理50万条级别的数据,你遇到的Maximum call stack size exceeded错误是因为默认的极值计算逻辑用了递归遍历,当数据量过大时超过了JavaScript引擎的调用栈限制。而VCL版本没问题,是因为桌面应用的运行环境栈限制远高于浏览器JS引擎,且VCL的TeeChart可能用了更高效的迭代式计算逻辑。

针对这个问题,给你几个实用的解决方案:

1. 手动设置坐标轴极值,跳过自动递归计算

错误栈显示问题出在计算minYValue的递归调用里——TeeChart默认会遍历所有数据点来计算坐标轴的最小/最大值,数据量到10万+时递归深度就会触发栈溢出。你可以自己预先计算数据的极值,然后直接赋值给坐标轴,这样就能避免自动计算的递归逻辑:

// 假设你已经生成了原始数据数组originalData
let minY = Infinity;
let maxY = -Infinity;
for (const val of originalData) {
  if (val < minY) minY = val;
  if (val > maxY) maxY = val;
}

// 给Y轴设置极值,留一点余量让图表更美观
Chart1.axes.left.minimum = minY * 0.99;
Chart1.axes.left.maximum = maxY * 1.01;

// 如果X轴也有类似问题,同样可以手动设置X的min/max

2. 对数据进行降采样(最推荐)

实际上,50万条数据在网页画布上是完全没必要全部渲染的——比如你的画布宽度是1000px,50万条点会重叠到肉眼无法区分的程度。降采样可以把数据精简到屏幕能显示的合理数量(比如2000个点),既解决栈溢出,又大幅提升渲染和交互性能:

function downsample(data, targetCount) {
  const step = Math.floor(data.length / targetCount);
  const sampled = [];
  // 按间隔采样
  for (let i = 0; i < data.length; i += step) {
    sampled.push(data[i]);
  }
  // 确保包含最后一个数据点,避免截断
  if (sampled[sampled.length - 1] !== data[data.length - 1]) {
    sampled.push(data[data.length - 1]);
  }
  return sampled;
}

// 使用示例:把50万条数据降到2000个点
const originalData = [];
for (let i = 0; i < 500000; i++) {
  originalData.push(Math.random() * 100); // 替换成你的实际数据生成逻辑
}
const sampledData = downsample(originalData, 2000);

// 将采样后的数据添加到Series
sampledData.forEach(val => Series.add(val));

3. 关闭或优化不必要的可视化元素

你的代码里设置了marks.drawEvery=120,但即使是50万条数据,每120个点显示一个标记,也会有4000+个标记,这会额外消耗性能。可以进一步增大drawEvery的数值,或者直接关闭标记(如果不是必须的):

// 要么增大间隔
Chart1.series.items[0].marks.drawEvery = 500;
// 要么直接隐藏标记
Chart1.series.items[0].marks.visible = false;

修改后的完整测试代码

结合上面的方案,你的测试代码可以改成这样:

function draw() {
  Chart1 = new Tee.Chart("canvas");
  Series = new Tee.Line(Chart1);
  Chart1.addSeries(Series);

  // 生成50万条随机数据
  const dataCount = 500000;
  const originalData = [];
  for (let i = 0; i < dataCount; i++) {
    originalData.push(Math.random() * 100);
  }

  // 降采样到2000个点
  const sampledData = downsample(originalData, 2000);

  // 添加采样后的数据到系列
  sampledData.forEach(val => Series.add(val));

  // 手动计算并设置Y轴极值
  let minY = Infinity;
  let maxY = -Infinity;
  for (const val of sampledData) {
    if (val < minY) minY = val;
    if (val > maxY) maxY = val;
  }
  Chart1.axes.left.minimum = minY * 0.99;
  Chart1.axes.left.maximum = maxY * 1.01;

  // 其他配置
  Chart1.axes.left.title.text = "[hPa]";
  Chart1.axes.bottom.title.text = "Date/Time";
  Chart1.axes.bottom.labels.dateFormat = "dd.mm.yy hh:mm";
  Chart1.series.items[0].marks.drawEvery = 50;
  Chart1.title.visible = false;
  Chart1.legend.visible = false;
  changeTheme(Chart1, "minimal");

  Chart1.draw();
}

// 降采样函数
function downsample(data, targetCount) {
  const step = Math.floor(data.length / targetCount);
  const sampled = [];
  for (let i = 0; i < data.length; i += step) {
    sampled.push(data[i]);
  }
  if (sampled[sampled.length - 1] !== data[data.length - 1]) {
    sampled.push(data[data.length - 1]);
  }
  return sampled;
}

通过这些调整,你应该能顺利渲染大量数据,同时保持图表的性能和可读性。

内容的提问来源于stack exchange,提问作者Michael Fischer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:47:45