API数据获取成功(304 Not Modified)但页面无法加载问题排查
问题排查:API数据获取成功但页面无法加载(304 Not Modified)
问题描述
API数据已成功获取,但页面无法加载展示,请求返回状态码为304 Not Modified。以下是相关HTML结构、原可正常运行的JavaScript代码,以及重构后出现问题的新JavaScript代码,需排查原因。
相关代码
HTML结构
<article data-index="1" data-status="inactive"> <div class="content" id="articleImage2"> <p id="hiddenObject"> Enter details <br> <select id="branch"> <option disabled selected>Branch</option> <option value="etc">ETC</option> <option value="mech">Mech</option> <option value="civil">Civil</option> <option value="pei">PEI</option> </select> <select id="semester"> <option disabled selected>Semester</option> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> <option value="8">8</option> </select><p> </p> <button class="form-button" type="button" onclick="navigate()"> Let's go!!! <i class="fas fa-rocket"></i> </button> </p> <p> </p> <div> <p>Question papers <ul> <li>Loading... ..</li> </ul> </p> </div> </div> </article>
原可正常运行的JavaScript代码
// forms let typeValue = function () { var branch = document.getElementById("branch").value; var semester = document.getElementById("semester").value; document.getElementById("hiddenObject").style.display = "none"; var type = `${branch}-${semester}`; return type; } function queryQuestionPaper(dataIn) { fetch(URL) .then((res) => res.json()) .then(({ result }) => { let list = document.querySelector("ul"); let firstListItem = document.querySelector("ul li"); if (result.length > 0) { // 移除占位内容 list.removeChild(firstListItem); result.forEach((data) => { if(data.type == dataIn) { let link = document.createElement('a'); let linkItem = document.createElement("li"); link.textContent = data.name; link.href= data.pdfUrl; linkItem.appendChild(link) list.appendChild(linkItem) } }) } }).catch((err) => console.error(err)); } if (window.location.pathname !== "/html/about.html") { queryQuestionPaper(typeValue); }
重构后的JavaScript代码
表单跳转部分
// forms function navigate() { var branch = document.getElementById("branch").value; var semester = document.getElementById("semester").value; const baseUrl = `./${branch}-${semester}.html`; window.location = baseUrl; }
说明:新URL由当前页面URL与构造的URL拼接而成,构造的URL会以斜杠(/)分隔添加到当前URL末尾。
类型解析部分
// queries // 根据页面类型选择查询条件 let type = function typeMaker() { const currentUrl = window.location.pathname; const urlParts = currentUrl.split("/"); const lastPart = urlParts[urlParts.length - 1]; const types = { "etc": [1, 2, 3, 4, 5, 6, 7, 8], "mecha": [1, 2, 3, 4, 5, 6, 7, 8], "civil": [1, 2, 3, 4, 5, 6, 7, 8], "pei": [1, 2, 3, 4, 5, 6, 7, 8] }; for (const [prefix, suffixes] of Object.entries(types)) { for (const suffix of suffixes) { const expected = `${prefix}-${suffix}.html`; if (lastPart === expected) { return `${prefix}-${suffix}`; } } } } let typeValue = type();
说明:types对象为键值对集合,键代表类别(如"etc"、"mecha"、"civil"),值为数字数组(如[1,2,3,4,5,6,7,8])。外层循环通过Object.entries()和解构赋值遍历types条目,内层循环遍历数字数组,生成预期URL并与当前URL最后部分匹配,匹配成功则返回${prefix}-${suffix}格式的字符串。
数据查询渲染部分
function queryQuestionPaper() { fetch(URL) .then((res) => res.json()) .then(({ result }) => { let list = document.querySelector("ul"); let firstListItem = document.querySelector("ul li"); if (result.length > 0) { // 移除占位内容 list.removeChild(firstListItem); result.forEach((data) => { if(data.type == typeValue) { let link = document.createElement('a'); let linkItem = document.createElement("li"); link.textContent = data.name; link.href= data.pdfUrl; linkItem.appendChild(link) list.appendChild(linkItem) } }) } }).catch((err) => console.error(err)); } if (window.location.pathname !== "/html/resources.html" && window.location.pathname !== "/html/about.html") { queryQuestionPaper(); }
排查分析
- 分支名称拼写不一致:表单中Mech分支的value是
mech,但重构代码的types对象里写的是mecha,导致URL匹配失败,typeValue返回undefined,后续data.type == typeValue的过滤条件永远不成立,没有内容渲染。 - 304缓存问题:304状态码表示浏览器使用本地缓存的响应,如果之前缓存了不匹配或空数据,会导致新请求无法获取最新内容,页面自然无法展示正确数据。
- 全局变量依赖问题:
typeValue作为全局变量,若页面加载时URL解析逻辑未执行完成,会导致其值异常,影响后续过滤。 - 无匹配数据时的处理缺失:当没有匹配的数据或API返回空时,页面仍会显示占位符或无提示,用户无法判断状态。
修复方案
1. 修正分支拼写不一致
将types对象中的"mecha"改为"mech",与表单选项value保持一致:
const types = { "etc": [1, 2, 3, 4, 5, 6, 7, 8], "mech": [1, 2, 3, 4, 5, 6, 7, 8], "civil": [1, 2, 3, 4, 5, 6, 7, 8], "pei": [1, 2, 3, 4, 5, 6, 7, 8] };
2. 处理304缓存问题
在fetch请求中添加缓存控制参数,强制获取最新数据:
fetch(URL, { cache: 'no-cache' // 或使用'reload'强制重新请求 })
3. 优化类型解析与全局变量问题
将typeValue的赋值和查询函数调用放在DOM加载完成事件中,避免DOM未就绪的问题,同时将typeValue作为参数传入查询函数,减少全局依赖:
document.addEventListener('DOMContentLoaded', () => { const typeValue = type(); if (window.location.pathname !== "/html/resources.html" && window.location.pathname !== "/html/about.html") { queryQuestionPaper(typeValue); } }); // 修改queryQuestionPaper函数接收参数 function queryQuestionPaper(typeValue) { // ... 原有逻辑,将全局typeValue替换为传入的参数 }
4. 增加异常与无数据提示
完善查询函数,处理无匹配数据、API空结果、请求错误等情况,给用户明确反馈:
function queryQuestionPaper(typeValue) { fetch(URL, { cache: 'no-cache' }) .then((res) => res.json()) .then(({ result }) => { const list = document.querySelector("ul"); const firstListItem = document.querySelector("ul li"); if (result.length > 0) { list.removeChild(firstListItem); // 先过滤匹配数据 const matchedData = result.filter(data => data.type === typeValue); if (matchedData.length === 0) { const noDataItem = document.createElement("li"); noDataItem.textContent = "未找到对应试卷"; list.appendChild(noDataItem); return; } matchedData.forEach((data) => { const link = document.createElement('a'); const linkItem = document.createElement("li"); link.textContent = data.name; link.href = data.pdfUrl; link.target = "_blank"; // 可选,新窗口打开链接 linkItem.appendChild(link); list.appendChild(linkItem); }); } else { firstListItem.textContent = "暂无数据"; } }).catch((err) => { console.error(err); const list = document.querySelector("ul"); const firstListItem = document.querySelector("ul li"); firstListItem.textContent = "加载失败,请稍后重试"; }); }
内容的提问来源于stack exchange,提问作者phukon
相关产品推荐
相关产品推荐

