JavaScript中fetch.then未在使用响应数据前完成执行的问题
解决异步数据加载前调用函数导致的空数组问题
你的核心问题是fetch是异步操作:脚本会先同步执行完所有同步代码(包括末尾的start()),之后才会执行fetch回调里的赋值逻辑,所以第一次调用start时firstList还是空数组。下面给你两种直接可行的解决方案:
方案1:在fetch回调里触发start
直接把start()放到fetch的成功回调中,确保只有当数据加载并解析完成后,才执行渲染逻辑:
let firstList = [] fetch(`${baseUrl}canList`, { method: 'GET' }).then((response) => { return response.json() // 简化嵌套的then链,更易读 }).then((jsonResponse) => { firstList = jsonResponse start() // 数据就绪后再调用start }).catch((err) => { console.log(`Error: ${err}`) })
方案2:用async/await正确实现(修正你之前的尝试)
如果你想用async/await,得把整个数据加载+渲染的逻辑放到async函数里,确保等待fetch完成后再调用start:
let firstList = [] async function loadAndRender() { try { const response = await fetch(`${baseUrl}canList`, { method: 'GET' }) firstList = await response.json() start() // 等数据加载完再执行渲染 } catch (err) { console.log(`Error: ${err}`) } } loadAndRender() // 执行这个异步函数,替代原来直接调用的start()
你之前尝试async/await没成功,大概率是只包装了fetch但没等待结果,或是没在异步函数里调用start,上面的写法能帮你避开这个问题。
额外优化建议
可以去掉全局变量的依赖,把数据直接传给start函数,逻辑更清晰:
// 修改start函数,接收数据参数 function start(listData) { listBox.innerText = '' const listContainer = document.createElement('div') // 加上const,避免全局变量污染 listContainer.classList.add('text-container') listBox.append(listContainer) listData.forEach(el => { const div = document.createElement('div') div.innerText = el listContainer.appendChild(div) // 直接用创建好的变量,不用重复querySelector }) addstyle() } // 对应修改fetch的回调 .then((jsonResponse) => { start(jsonResponse) // 直接把数据传入start }) // 或者async/await里 start(await response.json()) // 一步到位,甚至可以不用firstList全局变量
内容的提问来源于stack exchange,提问作者Jon Stewart
相关产品推荐
相关产品推荐

