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

Node.js中无法在函数外部获取用户token的问题求助

解决Node.js+Mongoose+GraphQL登录流程中无法获取Token的问题

你的核心问题是异步回调导致的变量作用域和执行顺序问题:

  • getAuthenticated和comparePassword采用回调式异步逻辑,但Resolver里的同步代码会先于回调执行,导致外部token变量还没被赋值就返回了。
  • 你给getAuthenticated加了async关键字,但内部还是用回调,并没有返回Promise,所以调用.then()会得到undefined。

以下是具体的修复方案:

1. 重构comparePassword为Promise风格

把回调式的密码比对改成返回Promise,方便后续用await处理:

UserSchema.methods.comparePassword = function(candidatePassword) {
  return new Promise((resolve, reject) => {
    bcrypt.compare(candidatePassword, this.password, (err, isMatch) => {
      if (err) return reject(err);
      resolve(isMatch);
    });
  });
};

2. 重构getAuthenticated方法,移除回调并返回Promise

完全用async/await重写,去掉回调参数,直接返回用户实例或抛出错误:

UserSchema.statics.getAuthenticated = async function(email, password) {
  // 查找用户
  const user = await this.findOne({ email });
  if (!user) throw new Error('用户不存在');

  // 比对密码
  const isMatch = await user.comparePassword(password);
  if (!isMatch) throw new Error('密码错误');

  // 处理登录尝试次数和锁定状态
  if (user.loginAttempts || user.lockUntil) {
    await user.updateOne({
      $set: { loginAttempts: 0 },
      $unset: { lockUntil: 1 }
    });
  }

  return user;
};

3. 修改登录Resolver,正确使用await获取用户并生成Token

现在可以在Resolver里以同步风格处理异步逻辑,确保Token能正确赋值:

login: async (_, { email, password }) => {
  try {
    // 等待用户认证完成
    const user = await User.getAuthenticated(email, password);
    // 生成Token
    const token = user.createToken();
    
    return { token };
  } catch (error) {
    // 可根据错误类型返回对应GraphQL错误
    throw new Error(error.message);
  }
},

额外可选方案

如果你不想修改原有方法,也可以用Node.js内置的util.promisify把回调函数转换成Promise:

const { promisify } = require('util');
const getAuthenticatedAsync = promisify(User.getAuthenticated);
// 在Resolver里使用:const user = await getAuthenticatedAsync(email, password)

但直接重构为Promise+async/await的代码可读性更高,更符合现代Node.js开发规范。

内容的提问来源于stack exchange,提问作者pelotador.1

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:47:39