【问题标题】:Mongoose returning document even though an error was thrown即使抛出错误,猫鼬也会返回文档
【发布时间】:2021-01-13 13:13:29
【问题描述】:

我有一个 Express.js 路由,可以通过用户名和密码从我的 MongoDB 数据库中检索用户。我的目标是从请求正文中获取用户名和密码,通过用户名找到用户,然后验证密码是否匹配。如果密码匹配,我想返回用户对象和 200 状态码,如果密码不匹配,我想返回 404 和错误消息。

目前我的路由正在运行,但始终返回用户,即使密码不匹配也是如此。我正在检查它们是否匹配并抛出错误,但它似乎没有像我预期的那样抛出。理想情况下,如果密码在我的服务调用中不匹配,我想抛出一个错误,并在我的路由中捕获它以返回正确的状态代码。

我尝试在我的路由中捕获错误并从服务返回一个被拒绝的承诺,但用户仍然返回。我的预感是findOne接受的回调是在记录返回后运行的?

我在控制台中收到 UnhandledPromiseRejectionWarning 对应的行,如果密码不匹配,我将抛出错误:

app_1            | GET /user 200 221 - 4.297 ms
app_1            | (node:257) UnhandledPromiseRejectionWarning: Error: Password does not match
app_1            |     at /usr/src/app/services/userService.ts:17:37
app_1            |     at Generator.next (<anonymous>)
app_1            |     at fulfilled (/usr/src/app/services/userService.ts:5:58)

server.ts

注意 我通过导入将find 重命名为findUser find as findUser

app.get('/user', authenticateToken, async (req: Request, res: Response): Promise<void> => {
    const user = await findUser(req.body.username, req.body.password);
    if (!user) {
      res.status(404).send();
      return;
    }
    res.status(200).send({ user });
});

userService.ts

const find = (username: string, password: string) => {
    return User.findOne({ username }, async (err: Error, user: any) => {
        if (err) throw err;
        const passwordMatches = await user.validatePassword(password);
        if (!passwordMatches) throw Error("Password does not match")
    });
}

user.ts(用户猫鼬模型)

import mongoose from 'mongoose';
import bcrypt from 'bcrypt';

interface User {
  username: string;
  password: string;
  isModified: (string: any) => boolean;
}
const SALT_WORK_FACTOR = 10;
const userSchema = new mongoose.Schema({
  username: { type: String, required: true, index: { unique: true } },
  password: {
    type: String,
    unique: false,
    required: true
  }
},
{ timestamps: true }
);

userSchema.pre('save', function(next) {
  const user = this as unknown as User;
  if (!user.isModified('password')) return next();
  bcrypt.genSalt(SALT_WORK_FACTOR, (err: any, salt: any) => {
      if (err) return next(err);

      bcrypt.hash(user.password, salt, function(err: any, hash: any) {
          if (err) return next(err);

          user.password = hash;
          next();
      });
  });
});

userSchema.methods.validatePassword = function (pass: string) {
  return bcrypt.compare(pass, this.password);
};

const User = mongoose.model('User', userSchema);

export { User };

【问题讨论】:

    标签: javascript typescript express mongoose


    【解决方案1】:

    在我的userService 中,我更改了使用findOne 查询的方式来解决这个问题。我从阅读Does mongoose findOne on model return a promise?得到这个想法

    const find = (username: string, password: string) => {
      return User.findOne({ username }).exec().then((user: any) => {
        const passwordMatches = user.validatePassword(password);
        if (!passwordMatches) throw Error("Password does not match")
        return user;
      });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-19
      • 1970-01-01
      • 2021-03-24
      • 2020-03-20
      • 1970-01-01
      相关资源
      最近更新 更多