2016-03-06 69 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,這樣你就可以擁有一個邏輯流程。