Node.js后端无法向React.js返回温度数据,报错res.send is not a function
问题原因
- 变量名冲突:你的
http.get回调函数里用了res作为参数,这和外层Express路由处理函数的res(Express响应对象)重名了,导致你在res.on("end")里调用的res其实是HTTP请求的响应对象,不是Express用来返回给前端的响应对象,所以会报错res.send is not a function(即使你用的是res.end,本质也是这个变量覆盖问题)。
修复方案
1. 修改变量名解决冲突
把http.get回调里的res改成其他名称(比如httpRes),这样就能正确引用外层的Express响应对象:
app.get("/gettemperature", (req, res) => { const email = req.query.email; let stmt = `SELECT * FROM users WHERE email=?`; let todo = [email]; db.query(stmt, todo, (err, results, fields) => { if (err) { console.error(err.message); // 错误时返回响应,避免前端挂起 return res.status(500).json({ error: err.message }); } if(results.length === 0 ){ return res.status(404).json({ error: "用户不存在" }); } let id = results[0].id; let getID = `SELECT * FROM controlModules WHERE deviceowner=?`; let getidData = [id]; db.query(getID, getidData, (err, resulta, fields) => { if (err) { console.error(err.message); return res.status(500).json({ error: err.message }); } if(resulta.length === 0){ return res.status(404).json({ error: "未找到对应设备" }); } let lanip = resulta[0].ipaddress; let url = "http://"+lanip+"/data"; // 将参数改为httpRes,避免和外层res冲突 http.get(url,(httpRes) => { let body = ""; httpRes.on("data", (chunk) => { body += chunk; }); httpRes.on("end", () => { try { let json = JSON.parse(body); const temp_actual = json.temperature.value; console.log(temp_actual); // 这里的res是外层的Express响应对象,可正常返回数据 res.json({ value: temp_actual }); } catch (error) { console.error(error.message); return res.status(500).json({ error: "解析温度数据失败" }); }; }); }).on("error", (error) => { console.error(error.message); return res.status(500).json({ error: "获取设备温度数据失败" }); }); }); }); });
2. 用async/await简化代码(避免回调地狱)
如果你的Node.js版本支持,可将回调逻辑改为async/await,代码更清晰,也能减少变量冲突风险:
// 先把数据库查询和HTTP请求包装成Promise const queryPromise = (sql, params) => { return new Promise((resolve, reject) => { db.query(sql, params, (err, results) => { if (err) reject(err); else resolve(results); }); }); }; const httpGetPromise = (url) => { return new Promise((resolve, reject) => { http.get(url, (res) => { let body = ""; res.on("data", chunk => body += chunk); res.on("end", () => resolve(body)); }).on("error", reject); }); }; app.get("/gettemperature", async (req, res) => { try { const email = req.query.email; const userResults = await queryPromise(`SELECT * FROM users WHERE email=?`, [email]); if (userResults.length === 0) { return res.status(404).json({ error: "用户不存在" }); } const id = userResults[0].id; const deviceResults = await queryPromise(`SELECT * FROM controlModules WHERE deviceowner=?`, [id]); if (deviceResults.length === 0) { return res.status(404).json({ error: "未找到对应设备" }); } const lanip = deviceResults[0].ipaddress; const url = `http://${lanip}/data`; const body = await httpGetPromise(url); const json = JSON.parse(body); const temp_actual = json.temperature.value; // Express的res.json方法自动设置Content-Type并序列化JSON res.json({ value: temp_actual }); } catch (err) { console.error(err.message); res.status(500).json({ error: err.message }); } });
关键注意事项
- 所有错误分支必须返回响应,否则前端会一直处于等待状态直到超时;
- 使用
res.json()可以替代手动设置Content-Type和JSON.stringify,Express会自动处理这些细节。
内容的提问来源于stack exchange,提问作者Ian Ducao
相关产品推荐
相关产品推荐

