MERN在线点餐应用获取产品信息失败,出现304状态码求助
在线点餐应用前端Fetch获取产品数据时遇到304状态码无法获取数据的解决方法
开发在线点餐应用时,前端通过fetch请求产品接口返回304状态码,导致无法获取到最新数据,以下结合你提供的代码给出排查和解决思路:
先明确304状态码的含义
304表示请求的资源未被修改,浏览器会直接使用本地缓存的旧响应,不会向服务器请求新数据。这并非错误,但会导致你拿不到最新的产品信息。
排查与解决方案
1. 修改前端Fetch的缓存策略
默认GET请求会启用浏览器缓存,你可以显式设置缓存模式,强制获取最新数据:
const fetchFoodType = async () => { const res = await fetch( `http://localhost:8080/product?category=${foodEndpoint}`, { headers: { Authorization: `Bearer ${token}`, }, method: "GET", cache: "no-cache", // 强制浏览器验证缓存有效性,若资源更新则返回新数据 // 或者使用 cache: "reload" 完全跳过缓存,直接请求服务器 } ); // ...后续逻辑 };
2. 完善前端错误处理
当前代码未处理非200状态的响应,比如304、401(token无效)等情况,添加状态判断避免空数据:
const fetchFoodType = async () => { try { const res = await fetch( `http://localhost:8080/product?category=${foodEndpoint}`, { headers: { Authorization: `Bearer ${token}` }, method: "GET", cache: "no-cache", } ); if (!res.ok) { if (res.status === 304) { // 从缓存读取之前存储的数据(如果有) const cachedData = sessionStorage.getItem(`products_${foodEndpoint}`); cachedData && setFilteredFoods(JSON.parse(cachedData)); console.log("使用缓存数据,若需最新数据可强制刷新"); } else { throw new Error(`请求失败:${res.status}`); } } else { const data = await res.json(); setFilteredFoods(data); // 将新数据存入缓存备用 sessionStorage.setItem(`products_${foodEndpoint}`, JSON.stringify(data)); } } catch (error) { console.error("获取产品数据失败:", error); } };
3. 后端添加缓存控制响应头
在后端接口中设置缓存规则,避免浏览器长期缓存旧数据:
productController.get("/", verifyToken, async (req, res) => { try { const products = await Product.find(req.query); // 设置缓存策略:禁止缓存,每次请求都从服务器获取 res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 或者设置缓存有效期:res.setHeader("Cache-Control", "max-age=600"); // 10分钟后过期 return res.status(200).json(products); } catch (error) { console.error(error); // 出错时返回明确的错误响应,避免前端无数据 return res.status(500).json({ msg: "获取产品数据失败", error: error.message }); } });
4. 检查权限中间件与Token有效性
304可能掩盖了权限问题,比如Token过期或无效,确保verifyToken中间件在Token无效时返回明确的错误:
// 示例verifyToken中间件(需检查你的authmiddleware.js) const verifyToken = (req, res, next) => { const authHeader = req.headers.authorization; if (authHeader) { const token = authHeader.split(" ")[1]; jwt.verify(token, process.env.JWT_SECRET, (err, user) => { if (err) { return res.status(401).json({ msg: "Token无效或已过期" }); } req.user = user; next(); }); } else { return res.status(401).json({ msg: "未提供授权Token" }); } };
5. 确认数据库中存在对应分类的数据
检查MongoDB的Product集合,是否存在category与foodEndpoint匹配的数据。可以在后端接口添加日志验证:
productController.get("/", verifyToken, async (req, res) => { try { console.log("当前查询分类:", req.query.category); const products = await Product.find(req.query); console.log("查询到的产品数量:", products.length); res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); return res.status(200).json(products); } catch (error) { console.error(error); return res.status(500).json({ msg: "获取产品数据失败", error: error.message }); } });
内容的提问来源于stack exchange,提问作者user20872939
相关产品推荐
相关产品推荐

