Chart.js双数据集自动更新时出现TypeError错误求助
Chart.js双数据集自动更新时出现TypeError错误求助
我帮你分析下这个问题哈,你遇到的TypeError: Cannot set properties of undefined (setting 'data')本质上是代码执行到myChart.data.datasets[1].data时,datasets[1]是undefined,所以没法给它的data属性赋值。结合你描述的“单独更新第一个数据集没问题,第二个就报错”的情况,我梳理了几个可能的原因,以及对应的解决方案:
核心问题:图表实例被重复创建,状态不稳定
你原来的代码里,loadData函数每次执行都会重新创建myChart实例,覆盖之前的变量。虽然你只调用了一次loadData(),但如果网络请求延迟,刚好赶上第一次updateChartData触发时,loadData还没完成图表初始化,或者某些意外情况导致图表的第二个数据集没被正确创建,就会出现这个报错。
解决方案:重构代码,分离图表初始化与数据更新
我给你调整了代码结构,把图表初始化和数据加载/更新分开,确保图表实例只创建一次,后续只更新数据,同时添加了必要的检查避免报错:
const ctx3 = document.getElementById('verteilerboxchart'); var displayVoltage = document.getElementById('displayVoltageVerteilerbox'); var displayCurrent = document.getElementById('displayCurrentVerteilerbox'); var myChart; // 只执行一次:初始化空图表,确保双数据集存在 function initChart() { if (!ctx3) { console.error("找不到verteilerboxchart画布元素!"); return; } myChart = new Chart(ctx3, { type: 'line', data: { labels: [], datasets: [{ label: 'Verteilerboxspannung in V', data: [], borderWidth: 1, borderColor: 'rgba(0,0,255,1)' }, { label: 'Verteilerboxstrom in A', data: [], borderWidth: 1, borderColor: 'rgba(255,0,0,1)' }] }, options: { scales: { y: { beginAtZero: true, ticks: { color: 'rgba(0,0,0,1)' } }, x: { beginAtZero: true, ticks: { color: 'rgba(0,0,0,1)' } } }, plugins: { legend: { labels: { color: 'rgba(0,0,0,1)' } } } } }); } // 加载初始数据并更新图表 async function loadData() { try { const response = await fetch('verteilerboxDb_into_website.php'); const data = await response.json(); console.log('从PHP获取的数据: ', data); const voltageValue = []; const time = []; const currentValue = []; data.forEach(rowData => { voltageValue.push(parseFloat(rowData.Spannung)); currentValue.push(parseFloat(rowData.Strom)); time.push(rowData.zeitstempel); }); // 更新当前电压显示 if (voltageValue.length > 0) { const VoltageAtMoment = voltageValue[voltageValue.length - 1]; if (displayVoltage) { displayVoltage.textContent = VoltageAtMoment; } else { console.error("找不到displayVoltageVerteilerbox元素!") } } // 更新当前电流显示 if (currentValue.length > 0) { const CurrentAtMoment = currentValue[currentValue.length - 1]; if (displayCurrent) { displayCurrent.textContent = CurrentAtMoment; } else { console.error("找不到displayCurrentVerteilerbox元素!") } } // 更新图表数据(先检查图表实例是否存在) if (myChart) { myChart.data.labels = time; myChart.data.datasets[0].data = voltageValue; myChart.data.datasets[1].data = currentValue; myChart.update(); } else { console.error("图表实例未初始化!"); } } catch (error) { console.error('加载数据失败: ', error); } } // 定时更新图表数据的函数 async function updateChartData() { try { const response = await fetch('verteilerboxDb_into_website.php'); const data = await response.json(); console.log('从PHP获取的更新数据: ', data); const voltageValue = []; const currentValue = []; const time = []; data.forEach(rowData => { voltageValue.push(parseFloat(rowData.Spannung)); currentValue.push(parseFloat(rowData.Strom)); time.push(rowData.zeitstempel); }); // 更新当前值显示 if (voltageValue.length > 0) { const VoltageAtMoment = voltageValue[voltageValue.length - 1]; if (displayVoltage) { displayVoltage.textContent = VoltageAtMoment; } else { console.error("找不到displayVoltageVerteilerbox元素!") } } if (currentValue.length > 0) { const CurrentAtMoment = currentValue[currentValue.length - 1]; if (displayCurrent) { displayCurrent.textContent = CurrentAtMoment; } else { console.error("找不到displayCurrentVerteilerbox元素!") } } // 关键检查:确保图表实例和双数据集都存在 if (!myChart) { console.error("图表实例不存在!"); return; } if (myChart.data.datasets.length < 2) { console.error("图表中数据集数量不足!"); return; } // 更新图表数据 myChart.data.labels = time; myChart.data.datasets[0].data = voltageValue; myChart.data.datasets[1].data = currentValue; myChart.update(); } catch (error) { console.error('更新数据失败', error); } } // 启动流程:初始化图表 -> 加载初始数据 -> 设置定时更新 initChart(); loadData(); var UpdateInterval = setInterval(updateChartData, 10000);
关键修改点说明
- 分离初始化与数据操作:
initChart只执行一次,提前创建好包含双数据集的空图表,避免每次加载数据都重建图表导致实例状态混乱。 - 添加安全检查:在更新数据前,先确认图表实例存在、数据集数量足够,防止访问undefined属性。
- 优化数据处理逻辑:去掉了不必要的ID数组,直接通过数组长度获取最新值,代码更简洁。
- 修复潜在语法问题:去掉了数据集定义中的尾逗号,避免旧浏览器解析错误。
额外调试建议
如果还是有问题,可以在updateChartData函数开头加一行打印:
console.log('当前图表数据集:', myChart?.data?.datasets);
这样就能直观看到datasets数组的内容,确认datasets[1]是否真的存在,帮助进一步定位问题。
备注:内容来源于stack exchange,提问作者Kasma456
相关产品推荐
相关产品推荐

