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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 19:22:56