Array.push()返回undefined求助:Chart.js数据获取异常
问题原因与解决方案
核心问题:forEach不支持异步回调
你的代码里的关键问题是**Array.forEach()无法配合async/await工作**:
forEach会同步遍历数组,完全忽略回调函数返回的Promise。await data.forEach(async (...) => {})本质上是等待undefined(因为forEach的返回值就是undefined),不会等待内部的fetch请求完成。- 当函数执行到
console.log(xdata)和return语句时,所有内部的异步请求还处于pending状态,此时xdata和ydata还是空数组。你看到控制台里数组有值,是因为浏览器控制台的实时引用特性——它显示的是数组的当前状态,而非执行console.log那一刻的状态,后续异步操作完成后数组被填充,控制台就自动更新了显示内容。 - 如果你调用
getChartData()时没有使用await,直接访问返回值的xdata/ydata,会得到undefined,因为此时你拿到的是一个未resolved的Promise对象,而非最终的返回值。
解决方案
方案1:用for...of循环替代forEach
for...of原生支持async/await,能确保每个异步操作完成后再进入下一次循环:
async function getChartData(){ const xdata = [] const ydata = [] const data = await (await fetch('http://projetoti.test/api/api.php?nome=all')).json() // 用for...of遍历,支持await等待异步操作 for (const sensor of data) { let sensor_data = await (await fetch(`http://projetoti.test/api/api.php?nome=${sensor.name}&history=true`)).json() let xtemp_arr = [] let ytemp_arr = [] Object.keys(sensor_data).forEach(sData => { xtemp_arr.push(sensor_data[sData].value) ytemp_arr.push(sensor_data[sData].time) }) xdata.push(xtemp_arr.slice()) ydata.push(ytemp_arr.slice()) } console.log(xdata) return { xdata, ydata} }
方案2:用Promise.all()并行处理请求(效率更高)
如果不需要串行请求,用Promise.all()可以同时发起所有传感器数据请求,大幅提升速度:
async function getChartData(){ const data = await (await fetch('http://projetoti.test/api/api.php?nome=all')).json() // 将每个传感器的请求包装为Promise,返回对应的数据组 const sensorPromises = data.map(async sensor => { const sensor_data = await (await fetch(`http://projetoti.test/api/api.php?nome=${sensor.name}&history=true`)).json() const xtemp_arr = [] const ytemp_arr = [] Object.keys(sensor_data).forEach(sData => { xtemp_arr.push(sensor_data[sData].value) ytemp_arr.push(sensor_data[sData].time) }) return { x: xtemp_arr.slice(), y: ytemp_arr.slice() } }) // 等待所有请求完成 const results = await Promise.all(sensorPromises) // 整理成最终的xdata和ydata数组 const xdata = results.map(res => res.x) const ydata = results.map(res => res.y) console.log(xdata) return { xdata, ydata} }
额外注意点
调用getChartData()时必须使用await或者.then()来获取返回值:
// 正确调用方式 async function renderChart() { const chartData = await getChartData() // 用chartData.xdata和chartData.ydata构建图表 } // 或者 getChartData().then(chartData => { // 处理图表数据 })
内容的提问来源于stack exchange,提问作者Goncalo
相关产品推荐
相关产品推荐

