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

页面加载时函数执行失败求助(附代码及报错信息)

页面初始加载时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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 09:15:24