2016-03-06 73 views
0

我需要保存到数据库之前验证用户名(如果提供了一个)和电子邮件(如果提供了一个)。我使用MongooseJS,但是,我不知道如何组织我的代码验证电子邮件和用户名,在清新的风格

这是我到目前为止有:

var user = new User(); 
if(req.body.email) { 
    User.findOne({"email" : req.body.email}, function(err, found){ 
     if(err) return next(err); 
     if(found) return res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Email address already exists"}); 
    }); 
} 

if(req.body.username) { 
    User.findOne({"username" : req.body.username}, function(err, found){ 
     if(err) return next(err); 
     if(found) return res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Username already exists"}); 
    }); 
} 

user.save(function(err){ 
    if(err) return next(err); 
    res.status(200).send(user); 
}); 

但当然,这将无法工作作为user.save会在任一验证块执行之前执行。我知道我可以把user.save回调中,但随后我会重复,我想避免的代码。

+1

有点偏离主题,但为什么您使用[状态码](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success)'200'发送一个错误信息?它不应该像'400'这样的东西来表明一个错误的请求? –

+0

我的API返回200的所有响应以及错误的详细信息。我的应用程序将返回400s到客户端。 – tommyd456

+0

可能与'$或'结合这两个查询条件如我的答案可能很简单... – zangw

回答

0

另一种简单的方法也许

var user = new User(); 
var email = req.body.email || ''; 
var username = req.body.username || ''; 

User.find({ 
      $or: [{"email": email}, {"username": username}]}, 
      function(err, users){ 
      if(err) return next(err); 
      if(users && users.length == 0) { 
       // save new user if none is matched 
       user.save(function(err){ 
         if(err) return next(err); 
         res.status(200).send(user); 
       }); 
      } else if (users && users.length > 0) { 
       // check users returned to determine which of following two error codes should be returned 
       //return res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Email address already exists"}); 
       //return res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Username already exists"}); 
      } 
}); 

你可以做到这一点通过Promise,这里是一个示例代码使用Q.js

function findUserByEmail() { 
    var deferred = Q.defer(); 
    if(req.body.email) { 
     User.findOne({"email" : req.body.email}, function(err, found){ 
      if(err) return deferred.reject(err); 
      if(found) { 
       res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Email address already exists"}); 
       deferred.reject(); 
      }else { 
       // no user is found, resolve it 
       deferred.resolve(); 
      } 
     }); 
    } else { 
     deferred.reject(); 
    } 
    return deferred.promise; 
} 

function findUserByName() { 
    var deferred = Q.defer(); 
    if(req.body.username) { 
     User.findOne({"username" : req.body.username}, function(err, found){ 
      if(err) return deferred.reject(err); 
      if(found) { 
       res.status(200).send({"error_code" : "INVALID_REQUEST_ERROR", "message" : "Username already exists"}); 
       deferred.reject(); 
      } else { 
       // no user is found, resolve it 
       deferred.resolve(); 
      } 
     }); 
    } else { 
     deferred.reject(); 
    } 
    return deferred.promise; 
} 

Q.all([findUserByName(), findUserByEmail()]).then (function() { 
    // in the resolve function, namely, no exist username and email 
    user.save(function(err){ 
     if(err) return next(err); 
     res.status(200).send(user); 
    }); 
}); 
+0

获取'错误:它们与你的诺言办法sent'后无法设置头 – tommyd456

+0

它的工作原理只有一个希望,但是不两者一起 – tommyd456

+0

@ tommyd456,对不起,以前的错误,请参阅更新的答案。 – zangw

0

的最好的办法是增加validation on to your mongoose Schema和让它在您尝试保存模型时自动执行(或者您可以先前调用验证函数)。像这样:

var userSchema = new Schema({ 
    email: { 
     type: String, 
     required: true, 
     validate: { 
      validator: function(v) { 
       var emailRegexp = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i; 

       return emailRegexp.test(v); 
      }, 
      message: "{VALUE} does not appear to be a valid email address." 
     } 
    } 
}); 

然后,当你尝试将其与不正确的数据保存:

var user = new User({ email: "this_isnt_a_proper_email" }); 

user.save(function(err) { 
    if (err.name === "ValidationError") { // check that it comes from mongoose validation 
     console.log(err.errors.email.message) 
     res.status(400).send({ validationError: err }); // send "Bad Request" HTTP header 
    } else { 
     res.send(user) // status 200 is implicit when not set 
    } 
}); 

为了更好地组织,检查是否有用户名或电子邮件数据库中已经设置了密码,我建议查找Bluebird(或类似的)Promises,这样你就可以拥有一个逻辑流程。