Express+Redis发起POST请求时HSET命令出现undefined参数类型错误
问题原因
报错提示HSET命令传入了undefined类型的参数,node_redis只允许字符串、日期、Buffer类型作为HSET的入参,所以触发异常。你代码中client.hset(uuid, "history", history, redis.print)一行的入参里,uuid或history两个变量存在undefined值。
排查与修复方案
- 修复路由大小写不匹配问题
你发起POST请求的路径是http://localhost:3001/history/additem(末尾为全小写additem),但代码中定义的路由是/history/addItem(字母I大写),默认express路由大小写敏感,匹配失败会导致jsonParser不会解析请求body,最终req.body为空,uuid和history都是undefined。
可以把路由改成全小写/history/additem,或者开启express大小写不敏感配置:
- 修复路由大小写不匹配问题
app.set('case sensitive routing', false)
- 增加请求参数校验与空值兜底
即使路由匹配正确,也要确保请求的JSON body中携带了uuid和history字段,同时对history的序列化增加空值兜底,避免req.body.history为undefined时JSON.stringify返回undefined:
- 增加请求参数校验与空值兜底
app.post('/history/additem', jsonParser, (req, res) => { // 先校验必填参数 if(!req.body?.uuid || req.body.history === undefined) { return res.status(400).send('缺少必填参数uuid或history') } connect.createConnection().then(client => { // 空值兜底,确保序列化后一定是字符串 const history = JSON.stringify(req.body.history ?? '') const uuid = req.body.uuid // 后续逻辑 }) })
- 修正Redis异步命令执行时序
Redis命令是异步执行的,你当前代码中hset还没执行完成就调用hgetall,可能会读取到旧数据甚至未写入的空数据,建议把hgetall放到hset的回调中执行:
- 修正Redis异步命令执行时序
client.hset(uuid, "history", history, (err) => { if(err) return res.send(err) client.hgetall(uuid, (err, results) => { client.quit() // 操作全部完成后再关闭连接 if(results){ res.send(results) }else{ res.send(err) } }) })
代码优化建议
每次请求都新建Redis连接再关闭的模式性能损耗很高,建议全局初始化一次Redis连接复用,不用每次请求都调用createConnection和quit。
内容的提问来源于stack exchange,提问作者Nezull
相关产品推荐
相关产品推荐

