You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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完全没覆盖异步逻辑。
  • 正确移除数组元素:
    • 如果你的User Schema中refreshToken是普通对象数组(比如refreshToken: [{ refreshToken: String }]),用splice直接删除对应索引的元素即可。
    • 如果是mongoose子文档数组,使用pull方法传入子文档_id更符合官方操作规范。
  • 修复返回内容错误:原代码返回user.refreshToken._id是逻辑错误,这里改为返回登出成功的提示信息,你也可以根据需求返回用户基础信息。
  • 增加用户存在性校验:避免找不到用户时后续操作触发额外报错。

内容的提问来源于stack exchange,提问作者Nasem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 20:15:10