Node.js中addFollower方法报hashed_password空值设置错误的排查方案
报错核心原因
TypeError: Cannot set property 'hashed_password' of null 的本质是 exec 回调中获取到的 result 值为 null,空对象本身不存在可赋值的属性,因此触发类型错误。结合你的代码链路,触发这个问题的常见场景有三个:
User.findByIdAndUpdate的查询条件不匹配:如果传入的req.body.followId在数据库中找不到对应文档,findByIdAndUpdate默认返回null,而你没有对返回结果做非空校验,直接执行赋值逻辑就会报错。- 路由串行中间件的参数错位:你的
/user/follow路由依次执行addFollowing、addFollower两个中间件,但当前代码完全没有做参数透传,很容易出现req.body.user_Id、req.body.followId字段缺失、值格式错误的问题,直接导致Mongoose查询匹配失败。 - 静默失败没有拦截:
findByIdAndUpdate的配置项没有开启校验规则,就算查询匹配、更新操作出现异常,也不会抛出明确错误,容易让问题隐蔽。
可落地的修复步骤
- 回调中补全非空判断,从代码逻辑上杜绝空值赋值
直接修改addFollower方法的回调逻辑,优先校验返回结果的有效性:exports.addFollower= (req,res )=>{ User.findByIdAndUpdate(req.body.followId, { $push:{followers: req.body.user_Id} }, {new : true, runValidators: true} ) .populate('following', '_id name') .populate('followers', '_id name') .exec((err,result)=>{ if(err){ return res.status(400).json({ error:"关注操作执行失败" }) } // 新增非空校验,拦截null场景 if (!result) { return res.status(404).json({ error: "要关注的用户不存在,请检查传入的followId" }) } result.hashed_password= undefined; result.salt = undefined; res.json(result) }) } - 梳理中间件的参数流转,解决字段缺失问题
按照关注接口的常规业务逻辑,两个串行中间件的职责是:addFollowing:给当前登录用户的following列表,添加目标关注用户的IDaddFollower:给目标关注用户的followers列表,添加当前登录用户的ID
你现在代码中在addFollower里使用的req.body.user_Id大概率不存在:requireSignin中间件解析token后,一般会把当前登录用户信息挂在req.auth对象上,而不是放在请求体req.body中。如果没有从前端传这个字段,查询时就会因为参数值为undefined匹配不到任何文档,最终返回null。
调整后的中间件可以通过透传参数的方式,避免依赖不确定的请求体字段:
// addFollowing 调整后代码 exports.addFollowing = (req, res, next) => { User.findByIdAndUpdate( req.auth._id, { $push: { following: req.body.followId } }, { new: true, runValidators: true } ).exec(err => { if (err) { return res.status(400).json({ error: "当前用户的关注列表更新失败" }) } // 把后续需要的参数挂载到req上,透传给下一个中间件 req.followTargetId = req.body.followId req.currentUserId = req.auth._id // 进入addFollower中间件 next() }) } // addFollower 调整后代码,使用透传的参数 exports.addFollower = (req, res) => { User.findByIdAndUpdate( req.followTargetId, { $push: { followers: req.currentUserId } }, { new: true, runValidators: true } ) .populate('following', '_id name') .populate('followers', '_id name') .exec((err, result) => { if (err || !result) { return res.status(400).json({ error: "目标用户的粉丝列表更新失败" }) } result.hashed_password = undefined; result.salt = undefined; res.json(result) }) } - 加上快速排查的调试语句
可以在exec回调的最开头打印两个值,快速定位问题:- 打印查询时使用的ID值:确认
req.body.followId是不是合法的24位MongoDB ObjectId字符串,有没有出现值为undefined、或者错传成当前登录用户ID的情况 - 打印回调拿到的
err和result内容:如果result为null,就说明数据库中确实找不到对应ID的用户,直接核对ID和数据库记录即可。
- 打印查询时使用的ID值:确认
额外注意:如果你的
userById中间件已经把目标用户信息挂载到了req.profile上,也可以直接复用这个值,不用重新调用findByIdAndUpdate查询,减少重复数据库请求。
内容的提问来源于stack exchange,提问作者Naveen DINUSHKA
相关产品推荐
相关产品推荐

