使用res.render渲染HTML时,Ajax获取MongoDB数据及/items路由无法返回JSON问题
问题分析与解决方案
首先看你现有代码里的几个关键问题:
- 你的路由路径是
/items,但代码里用了req.params.id——这里根本没有定义:id参数,所以req.params.id是undefined,导致Item.findById查询不到任何数据。 - 当前路由用
res.render返回的是渲染后的HTML页面,不是JSON格式,所以$.getJSON请求会因为返回内容不是合法JSON而解析失败。
下面给你两种可行的解决思路:
思路一:拆分路由,分别处理页面渲染和JSON请求
把页面渲染和数据接口分开,这样逻辑更清晰:
1. 修正页面渲染路由(带物品ID参数)
app.get("/items/:id", middleware.isLoggedIn, function(req, res) { Item.findById(req.params.id, function(err, item) { if(err){ console.log(err); res.redirect("/"); // 查询失败时跳转到首页或错误页 }else{ res.render("buildings/items", {item : item}); } }); });
2. 添加返回JSON的API路由
可以做两个接口:一个返回单个物品,一个返回所有物品(按需选择):
// 获取单个物品的JSON数据 app.get("/api/items/:id", middleware.isLoggedIn, function(req, res) { Item.findById(req.params.id, function(err, item) { if(err){ console.log(err); res.status(500).json({error: "获取物品失败"}); }else{ res.json(item); // 直接返回JSON格式的物品数据 } }); }); // (可选)获取所有物品的JSON数据 app.get("/api/items", middleware.isLoggedIn, function(req, res) { Item.find({}, function(err, items) { if(err){ console.log(err); res.status(500).json({error: "获取物品列表失败"}); }else{ res.json(items); } }); });
3. 修改Ajax请求对应的接口
比如你要获取某个ID的物品数据,就请求对应的API路由:
$(document).ready(function(){ // 替换成你实际要获取的物品ID const targetItemId = "xxx123xxx"; $.getJSON(`/api/items/${targetItemId}`) .then(function(data){ console.log("获取到的物品数据:", data); // 这里可以把数据渲染到页面上,比如更新DOM }) .catch(function(error){ console.error("请求出错:", error); }); });
思路二:同一个路由根据请求类型返回不同内容(内容协商)
如果不想拆分路由,可以让路由根据请求的Accept头判断:如果是Ajax的JSON请求,就返回JSON;否则返回HTML页面:
app.get("/items/:id", middleware.isLoggedIn, function(req, res) { Item.findById(req.params.id, function(err, item) { if(err){ console.log(err); // 根据请求类型返回对应格式的错误 if(req.accepts("json")) { res.status(500).json({error: "获取物品失败"}); } else { res.redirect("/"); } }else{ // 判断请求希望接收的格式 if(req.accepts("json")) { res.json(item); } else { res.render("buildings/items", {item : item}); } } }); });
这种情况下,你的原Ajax代码只需要补上ID参数就能用了:
$(document).ready(function(){ const targetItemId = "xxx123xxx"; $.getJSON(`/items/${targetItemId}`) .then(function(data){ console.log(data); }) .catch(function(err){ console.error(err); }); });
最后还要提醒你:确保middleware.isLoggedIn不会拦截Ajax请求——如果你的登录是基于Session的,同域下Ajax请求会自动携带Cookie,一般没问题;如果是Token认证,记得在请求头里带上Token。
内容的提问来源于stack exchange,提问作者Farbod
相关产品推荐
相关产品推荐

