页面加载时函数执行失败求助(附代码及报错信息)
页面初始加载时JSON数据渲染失败,点击切换功能正常
问题描述
完成Frontend Mentor项目时遇到以下问题:页面初始加载时,从JSON文件获取数据并渲染的函数执行失败,但通过点击switchItems触发的点击事件调用该函数可正常执行。
相关代码
const activityNames = document.querySelectorAll('.activity-name') const switchItems = document.querySelectorAll('.switch-item') const daily = document.querySelector('#daily') const weekly = document.querySelector('#weekly') const monthly = document.querySelector('#monthly') let finalData = {} let dataRange = 'daily' loadData() async function getData() { const response = await fetch('data.json') const data = await response.json() finalData = data console.log(finalData) } async function loadData() { getData() const acitivityTimesCurrent = document.querySelectorAll('.activity-time-current') const activityTimesPrevious = document.querySelectorAll('.activity-time-previous') if (dataRange === 'daily') { acitivityTimesCurrent.forEach(function (activity, index) { const currentDaily = finalData[index].timeframes.daily.current activity.textContent = currentDaily === 1 ? finalData[index].timeframes.daily.current + 'hr' : finalData[index].timeframes.daily.current + 'hrs' }) activityTimesPrevious.forEach(function (activity, index) { const previousDaily = finalData[index].timeframes.daily.previous activity.textContent = previousDaily === 1 ? 'Yesterday - ' + finalData[index].timeframes.daily.previous + 'hr' : 'Yesterday - ' + finalData[index].timeframes.daily.previous + 'hrs' }) } else if (dataRange === 'weekly') { acitivityTimesCurrent.forEach(function (activity, index) { const currentWeekly = finalData[index].timeframes.weekly.current activity.textContent = currentWeekly === 1 ? finalData[index].timeframes.weekly.current + 'hr' : finalData[index].timeframes.weekly.current + 'hrs' }) activityTimesPrevious.forEach(function (activity, index) { const previousWeekly = finalData[index].timeframes.weekly.previous activity.textContent = previousWeekly === 1 ? 'Last week - ' + finalData[index].timeframes.weekly.previous + 'hr' : 'Last week - ' + finalData[index].timeframes.weekly.previous + 'hrs' }) } else { acitivityTimesCurrent.forEach(function (activity, index) { const currentMonthly = finalData[index].timeframes.monthly.current activity.textContent = currentMonthly === 1 ? finalData[index].timeframes.monthly.current + 'hr' : finalData[index].timeframes.monthly.current + 'hrs' }) activityTimesPrevious.forEach(function (activity, index) { const previousMonthly = finalData[index].timeframes.monthly.previous activity.textContent = previousMonthly === 1 ? 'Last month - ' + finalData[index].timeframes.monthly.previous + 'hr' : 'Last month - ' + finalData[index].timeframes.monthly.previous + 'hrs' }) } } switchItems.forEach(item => { item.addEventListener('click', (e) => { deleteActive() dataRange = e.target.dataset.value item.classList.add('active') loadData() }) }) function deleteActive() { const switchItems = document.querySelectorAll('.switch-item') switchItems.forEach(item => { item.classList.remove('active') }) }
报错信息
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'timeframes') at script.js:26:51 at NodeList.forEach (<anonymous>) at loadData (script.js:25:31) at script.js:10:1
问题原因
getData是异步函数,执行时会先发起网络请求,然后继续执行后续代码。初始调用loadData时,直接调用getData()但没有等待其完成,此时finalData还是初始的空对象{},尝试访问finalData[index]会得到undefined,自然无法读取timeframes属性,导致报错。
而点击事件触发时,getData已经在页面加载时完成了请求,finalData已经被赋值为JSON数据,所以loadData可以正常执行。
解决方案
- 修改
loadData函数,使用await等待getData异步操作完成,确保数据获取后再执行渲染:
async function loadData() { await getData() // 等待数据获取完成 const acitivityTimesCurrent = document.querySelectorAll('.activity-time-current') const activityTimesPrevious = document.querySelectorAll('.activity-time-previous') // 后续渲染逻辑保持不变 }
- 调整初始调用
loadData的方式,用异步立即执行函数包裹,处理异步调用:
// 替换原有的 loadData() (async () => { await loadData() })()
- 可选:给
getData添加错误处理,避免请求失败引发异常:
async function getData() { try { const response = await fetch('data.json') if (!response.ok) { throw new Error(`HTTP请求失败,状态码: ${response.status}`) } const data = await response.json() finalData = data console.log(finalData) } catch (error) { console.error('加载数据出错:', error) } }
内容的提问来源于stack exchange,提问作者Tomasz
相关产品推荐
相关产品推荐

