使用passport-jwt开发登出路由时出现TypeError错误的解决求助
问题修复方案
错误原因
你遇到的TypeError: user.refreshToken.id(...).remove is not a function,核心是mongoose数组的子文档操作方式有误,同时代码的异步逻辑处理也存在漏洞。
修正后的代码
router.get("/logout", verifyUser, async (req, res, next) => { const { signedCookies = {} } = req; const { refreshToken } = signedCookies; try { // 用await替代链式then,让异步逻辑更清晰可控 const user = await User.findById(req.user._id); if (!user) { return res.status(404).send({ success: false, message: "用户不存在" }); } // 定位要移除的refreshToken在数组中的位置 const tokenIndex = user.refreshToken.findIndex( (item) => item.refreshToken === refreshToken ); if (tokenIndex !== -1) { // 方式1:适用于普通对象数组,直接通过splice删除元素 user.refreshToken.splice(tokenIndex, 1); // 方式2:如果refreshToken是mongoose子文档数组,用pull方法更规范 // user.refreshToken.pull({ _id: user.refreshToken[tokenIndex]._id }); } // 等待用户数据保存完成 await user.save(); res.clearCookie("refreshToken", COOKIE_OPTIONS); // 修正原错误的返回字段,返回合理的登出成功提示 res.send({ success: true, message: "登出成功" }); } catch (error) { res.status(500).send({ success: false, error: error.message }); } });
关键修改说明
- 统一异步处理逻辑:把
.then()改为async/await,让try/catch能真正捕获user.save()这类异步操作的错误,原代码的try/catch完全没覆盖异步逻辑。 - 正确移除数组元素:
- 如果你的
UserSchema中refreshToken是普通对象数组(比如refreshToken: [{ refreshToken: String }]),用splice直接删除对应索引的元素即可。 - 如果是mongoose子文档数组,使用
pull方法传入子文档_id更符合官方操作规范。
- 如果你的
- 修复返回内容错误:原代码返回
user.refreshToken._id是逻辑错误,这里改为返回登出成功的提示信息,你也可以根据需求返回用户基础信息。 - 增加用户存在性校验:避免找不到用户时后续操作触发额外报错。
内容的提问来源于stack exchange,提问作者Nasem
相关产品推荐
相关产品推荐

