POST请求插入PostgreSQL表行成功但未携带数据问题排查
故障根本原因
请求体为空的核心问题出在客户端序列化逻辑错误,附带存在服务端取值的潜在问题,具体如下:
- 核心错误:当前代码里
JSON.stringify(e.target)是在序列化DOM单元格元素。DOM元素属于浏览器原生宿主对象,存在大量原型链属性、循环引用,几乎没有自身可枚举的普通属性,JSON.stringify处理这类对象时只会序列化对象自身的可枚举属性,最终输出结果就是空对象{},这就是服务端打印req.body为空的直接原因。 - 之前尝试的两种写法同样存在逻辑错误:
JSON.stringify(e.value.innerText):DOM点击事件对象e不存在value属性,e.value为undefined,读取undefined的innerText会直接触发JS报错,请求根本无法正常发送JSON.stringify(e.target.name):创建的单元格是<td>元素,全程没有给该元素设置过name属性,e.target.name本身就是undefined,序列化后不会传递有效内容
- 潜在问题:当前服务端逻辑直接把整个
req.body对象作为SQL参数传入,就算传了正确数据,最终写入数据库的也会是[object Object]字符串,拿不到正确的名称值;如果服务端没注册express.json()中间件,即使客户端传了正确JSON,服务端也无法正常解析请求体。
修复方案
1. 客户端代码修正
不需要从事件对象绕弯取值,循环作用域里已经提前拿到了处理好的影片名称,直接构造普通可序列化的JS对象传参即可,修改点击事件里的fetch逻辑:
newCell.onclick = async function(e) { if (!color) { e.target.style.backgroundImage = 'linear-gradient(to right, black, greenyellow)'; e.target.style.color = 'white'; const response = await fetch("http://localhost:5000/movies", { method: "POST", headers: {"Content-type":"application/json"}, // 直接构造普通对象传值,不要序列化DOM节点 body: JSON.stringify({ name: newCell.innerText.trim() }) }); color = true; } else { e.target.style.backgroundImage = 'linear-gradient(to right, black, red)'; color = false; } }
2. 服务端代码修正
确认路由定义前已注册JSON解析中间件,从请求体中取对应字段传入SQL:
// 必须在路由定义前添加这行,否则无法解析JSON请求体 app.use(express.json()); app.post('/movies', async (req,res) => { try { // 从请求体结构出name字段,不要传入整个req.body对象 const { name } = req.body; console.log('接收到的影片名:', name); const newMovie = await pool.query("INSERT INTO movies (name) VALUES($1) RETURNING *", [name]); res.json(newMovie.rows[0]); } catch(err) { console.error(err.message) res.status(500).json({err: err.message}) } })
注意:
JSON.stringify只能处理普通JS对象、数组、基础类型值,不能直接序列化DOM节点、函数、含循环引用的对象这类特殊值,这类值序列化后要么为空、要么丢失属性、要么直接抛错。
内容的提问来源于stack exchange,提问作者user19308961
相关产品推荐
相关产品推荐

