页面加载时从JSON读取车站数据到数组后无法正常显示的问题
问题:页面加载/重载时无法正常显示车站全名
开发展示预选车站发车信息的Web应用,选中车站ID存储在cookie中。将包含车站ID与全名的JSON文件读取到数组Stations,以ID为键、全名为值存储(Stations[Id] = FullName)。目前存在以下问题:
- 控制台输出
Stations数据正常,但页面打开或重载时,checkCookie()函数在页面上显示undefined而非车站名称 - 选择新车站并执行
setCookie()函数后,车站全名可正常显示 - 已尝试将
checkCookie()设为async并等待loadStations()完成,问题仍未解决
原代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script> var Stations = []; function onLoad() { checkCookie(); return; } async function loadStations() { fetch("tinystations.json") .then(response => response.json()) .then(stations => stations.forEach(item => Stations[item.Id] = item.FullName)); return; } async function checkCookie() { await loadStations(); console.log(Stations); var station1 = getCookie("station1"); document.getElementById("chosen1").innerHTML = station1 + " : " + Stations[station1]; return; } function setCookie() { const d = new Date(); d.setTime(d.getTime() + 100000000000); // Sufficiant amount of time. 3 years. let expires = "expires=" + d.toUTCString(); let station1 = document.getElementById("TIstation1").value; document.cookie = "station1=" + station1 + ";" + expires; document.getElementById("chosen1").innerHTML = station1 + " : " + Stations[station1]; return; } function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); } </script> </head> <body onload="onLoad()"> <div id="coockie"> <p>Select new stations</p> <input id="TIstation1" type="text" placeholder="Choose station" /> <button onclick="setCookie()">Save</button> </div> <div id="chosen"> Preselected: <p id="chosen1"> </p> </div> </body> </html>
JSON文件内容
[ { "FullName": "Arlanda C", "Id": "Arnc" }, { "FullName": "Huddinge", "Id": "Hu" }, { "FullName": "Jakobsberg", "Id": "Jkb" }, { "FullName": "Stuvsta", "Id": "Stu" }, { "FullName": "Rotebro", "Id": "R" }, { "FullName": "Stockholm City", "Id": "Sci" } ]
问题原因与修复方案
核心问题
loadStations函数标记为async,但内部的fetch调用没有返回Promise,导致await loadStations()无法真正等待JSON数据加载完成。checkCookie会在Stations还未填充数据时就执行DOM更新,因此显示undefined。
修复步骤
- 让
loadStations返回Promise:修改函数使其返回fetch的Promise链,确保await能正确等待数据加载完成。 - 将
Stations改为对象(可选但更合理):因为使用字符串作为键,对象比数组更符合键值对的语义,避免数组索引混淆问题。 - 增加空值判断:避免cookie不存在或车站ID无效时显示异常内容。
修改后的完整代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script> // 改为对象存储键值对更合理 var Stations = {}; function onLoad() { checkCookie(); } async function loadStations() { // 返回fetch的Promise链,让await能正确等待数据加载 return fetch("tinystations.json") .then(response => { // 增加请求错误处理 if (!response.ok) throw new Error("车站数据加载失败"); return response.json(); }) .then(stations => stations.forEach(item => Stations[item.Id] = item.FullName)) .catch(err => console.error(err)); } async function checkCookie() { await loadStations(); console.log(Stations); var station1 = getCookie("station1"); // 增加空值判断,优化显示 if (station1 && Stations[station1]) { document.getElementById("chosen1").innerHTML = `${station1} : ${Stations[station1]}`; } else { document.getElementById("chosen1").innerHTML = station1 ? `无效车站ID: ${station1}` : "未选择车站"; } } function setCookie() { const d = new Date(); d.setTime(d.getTime() + 100000000000); // 约3年有效期 let expires = "expires=" + d.toUTCString(); let station1 = document.getElementById("TIstation1").value; document.cookie = "station1=" + station1 + ";" + expires; document.getElementById("chosen1").innerHTML = station1 + " : " + (Stations[station1] || "无效车站ID"); } function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); } </script> </head> <body onload="onLoad()"> <div id="coockie"> <p>Select new stations</p> <input id="TIstation1" type="text" placeholder="Choose station" /> <button onclick="setCookie()">Save</button> </div> <div id="chosen"> Preselected: <p id="chosen1"> </p> </div> </body> </html>
额外说明
- 新增的错误处理可以在网络请求失败时在控制台输出提示,便于调试
- 空值判断提升了用户体验,避免页面显示无意义的
undefined - 使用对象存储车站数据,更符合键值对的使用场景,代码语义更清晰
内容的提问来源于stack exchange,提问作者Clas Östman
相关产品推荐
相关产品推荐

