2016-03-06 5 views
0

Мне нужно подтвердить имя пользователя (если оно указано) и электронное письмо (если оно предусмотрено) перед сохранением в db. Я использую 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

My 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

Получение 'Ошибка: невозможно установить заголовки после их отправки' с вашим подходом к обещанию – 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 (или аналогичный). Обещает, так что вы можете иметь логический поток к процессу.

Смежные вопросы