MERN栈博客集成报错:SyntaxError: Unexpected token '<'
解决MERN栈博客功能中
SyntaxError: Unexpected token '<'错误 你遇到的这个错误本质是前端请求API后收到的不是JSON数据,而是HTML文档(大概率是404页面或者前端的index.html),导致response.json()解析失败。结合你提供的代码和MERN栈的常见问题,给出以下排查和解决步骤:
一、核心原因分析
这个报错的直接触发点是await response.json()尝试解析HTML内容(比如<!doctype html>开头的字符串),而不是预期的JSON。通常由以下几种情况导致:
- 前后端路由路径不匹配,后端没有找到对应的API接口,返回了前端的 fallback 页面
- 后端路由挂载路径错误,前端请求的URL和实际API地址不符
- 后端错误处理返回了纯文本而非JSON,导致解析失败
二、具体解决方案
1. 核对API请求路径是否正确
检查后端路由的挂载方式:
如果你的后端是这样挂载博客路由的:
// 示例:假设挂载在/api前缀下 app.use('/api/blog', blogRouter);
那前端请求的URL应该是${host}/api/blog/blogs,而不是你当前写的${host}/blog/blogs。
2. 调整后端路由顺序
MERN栈中,后端需要优先处理API路由,再处理前端静态文件和路由 fallback。确保你的后端代码顺序是:
// 1. 先配置所有API路由 app.use('/api/blog', blogRouter); // 2. 再处理前端静态文件 app.use(express.static(path.join(__dirname, '../client/build'))); // 3. 最后处理前端路由的 fallback(返回index.html) app.get('*', (req, res) => { res.sendFile(path.join(__dirname, '../client/build/index.html')); });
如果把API路由写在app.get('*', ...)之后,所有请求都会被返回index.html,自然无法获取JSON数据。
3. 统一后端错误返回格式
你的后端错误处理目前返回的是纯文本,改成JSON格式,避免前端解析异常:
router.get('/blogs', async (req, res) => { try { const blogPosts = await BlogPost.find(); res.json({blogPosts: blogPosts}); } catch (error) { // 把send改成json返回错误信息 res.status(500).json({error: "Some Error occurred"}); } });
4. 前端增加响应状态校验
在解析JSON前先检查响应状态,提前捕获错误:
useEffect(() => { const fetchBlogs = async () => { try { const url = `${host}/blog/blogs`; const response = await fetch(url, { method: "GET", headers: { "Content-Type": "application/json", "authtoken": localStorage.getItem("token") }, }); // 新增:检查响应是否成功 if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } const allblogs = await response.json(); setBlogs(allblogs); setLoading(false); extractUniqueTags(allblogs); } catch (error) { console.error('获取博客失败:', error.message); setLoading(false); } }; fetchBlogs(); // eslint-disable-next-line }, []);
附:你提供的原始代码
前端获取数据代码
useEffect(() => { const fetchBlogs = async () => { try { const url = `${host}/blog/blogs`; const response = await fetch(url, { method: "GET", headers: { "Content-Type": "application/json", "authtoken": localStorage.getItem("token") }, }); const allblogs = await response.json(); setBlogs(allblogs); setLoading(false); extractUniqueTags(allblogs); } catch (error) { console.error('Error fetching blogs:', error.message); setLoading(false); } }; fetchBlogs(); // eslint-disable-next-line }, []);
后端返回数据代码
router.get('/blogs', async (req, res) => { try { const blogPosts = await BlogPost.find(); res.json({blogPosts: blogPosts}); } catch (error) { res.status(500).send("Some Error occurred"); } });
内容的提问来源于stack exchange,提问作者Sainty
相关产品推荐
相关产品推荐

