使用异步等待的Mongoose查询

时间:2018-03-01 16:14:13

标签: javascript node.js express mongoose async-await

我有一个应用程序,登录用户可以创建新用户并将其添加到其中一个组。您可以在路径中看到此中间件流:

router.post('/account/add-users',
  userController.validateRegister,
  userController.registerUser,
  userController.getNewUser,
  groupController.addUserToGroup
);

我正在使用Passport进行注册/身份验证。

基本上,一旦我注册了新用户,我希望能够将它们添加到创建者指定的组中。

我的validateRegister方法如下:

exports.validateRegister = (req, res, next) => {
 req.sanitizeBody('name');
 req.checkBody('name', 'You must supply a name!').notEmpty();
 if(req.body.email){
  req.checkBody('email', 'That Email is not valid!').isEmail();
  req.sanitizeBody('email').normalizeEmail({
   gmail_remove_dots: false,
   remove_extension: false,
   gmail_remove_subaddress: false
  });
  req.checkBody('password', 'Password Cannot be Blank!').notEmpty();
  req.checkBody('password-confirm', 'Confirmed Password cannot be blank!').notEmpty();
  req.checkBody('password-confirm', 'Oops! Your passwords do not match').equals(req.body.password);  
  };
  const errors = req.validationErrors();
 if (errors) {
    req.flash('error', errors.map(err => err.msg));
    res.render('login', { title: 'Register', body: req.body, flashes: 
    req.flash() });
    return; // stop the fn from running
  }
  next(); // there were no errors!
};

registerUser是:

exports.registerUser = async (req, res, next) => {
  console.log('registering user');
  if(req.body.email){
    await User.register(new User({email: req.body.email, name: 
    req.body.name, userType: req.body.userType}), 
    req.body.password, 
    function(err) {
      if (err) {
        console.log('error while user register!', err);
        return next(err);
      }
      console.log('user registered!');                      
      res.redirect('/');
     }
   );
} else {
  console.log('NO EMAIL PROVIDED');
  await User.register(new User({name: req.body.name, userType: 
  req.body.userType}), 
  req.body.password, 
  function(err) {
      if (err) {
        console.log('error while user register!', err);

        return next(err);
      }        
    });
 };
 console.log(' user registered!');

// the below are values from the form that I will need to add users to a group
 res.locals.chosenGroup = req.body.group; 
 res.locals.newUserUserName = req.body.name;
 res.locals.newUserUserType = req.body.userType;
 next();
 };

getNewUser在下面,这就是事情发生的地方。 console.log将正确打印res.locals.newUserUserName的值,但当我尝试在User.find中使用该值时,没有任何内容返回

exports.getNewUser = async (req, res, next) => {
  console.log('IN GETNEWUSER '+res.locals.newUserUserName);
  res.locals.newUser = await User.find( { "name" : 
  res.locals.newUserUserName } );
  if (!res.locals.newUser) {
    console.log('User is not available yet!');
  } else {
    console.log('USER IN REGSITER USER FUNCTION IN GETNEWUSER METHOD 
    '+res.locals.newUser);
  }
 next();
};

我认为这是因为用户尚未进入数据库(如果我将用户名称硬编码到查询中并再次执行该过程,则会返回正确的记录,这表明这是一个时间问题)所以我猜我的async / awaits做错了。但console.log(' user registered!')中的registerUser显示在getNewUser中的任何日志之前的终端中,所以我有点难过!

---- ----编辑

好的,所以如果在registerUser中我使用Promisify来重写

User.register(new User({name: req.body.name, userType: 
req.body.userType}), 
req.body.password, 

function(err) {
  if (err) {
    console.log('error while user register!', err);

    return next(err);
  }        
});

const user = new User({ name: req.body.name, userType: req.body.userType });
const register = promisify(User.register, User);
await register(user, req.body.password);
然后一切正常。我真的很想理解为什么。

2 个答案:

答案 0 :(得分:0)

在你的registerUser函数中,似乎user.Register()使用了一个回调,因此它不需要等待"你是否尝试从这两行中删除async / await并再次测试它?

答案 1 :(得分:0)

我相信你在User.Register回调之前调用了下一个中间件,这就是它不能在下一个中间件上创建的原因。

您可以尝试以下代码段吗?

exports.registerUser = async (req, res, next) => {
  console.log('registering user');
  if (req.body.email) {
    await User.register(new User({
        email: req.body.email, 
        name: req.body.name, 
        userType: req.body.userType
      }),
      req.body.password,
      function (err) {
        if (err) {
          console.log('error while user register!', err);
          return next(err);
        }
        console.log('user registered!');

        // this calls the userController.getNewUser only after the user registers
        // I'm not sure you need set the res.locals variables here as well
        next();
      }
    );
  } else {
    console.log('NO EMAIL PROVIDED');
    await User.register(new User({
        name: req.body.name, 
        userType: req.body.userType
      }),
      req.body.password,
      function (err) {
        if (err) {
          console.log('error while user register!', err);
          return next(err);
        }
        console.log(' user registered!');

        // the below are values from the form that I will need to add users to a group
        res.locals.chosenGroup = req.body.group;
        res.locals.newUserUserName = req.body.name;
        res.locals.newUserUserType = req.body.userType;
        next();
      });
  }
};