Лучший способ проверить ошибку проверки мангуста
У меня есть две функции validation для моего usermodel
User.schema.path('email').validate(function(value, respond) {
User.findOne({email: value}, function(err, user) {
if(err) throw err;
if(user) return respond(false);
respond(true);
});
}, 'EMAIL_EXISTS');
и то же самое для username
User.schema.path('username').validate(function(value, respond) {
User.findOne({username: value}, function(err, user) {
if(err) throw err;
if(user) return respond(false);
respond(true);
});
}, 'USERNAME_TAKEN');
Они возвращают ошибки в следующем формате
{ message: 'Validation failed',
name: 'ValidationError',
errors:
{ username:
{ message: 'Validator "USERNAME_TAKEN" failed for path username',
name: 'ValidatorError',
path: 'username',
type: 'USERNAME_TAKEN' } } }
Ошибка для пути email
аналогична. Есть ли более эффективный способ проверить эти ошибки, чем следующие?
if (err && err.errors && err.errors.username) { ... }
Это отвратительно.
Ответы
Ответ 1
Технически вы должны сначала проверить имя ошибки, потому что не все ошибки обрабатываются одинаково. Затем, основываясь на имени ошибки, вы должны проверить определенные свойства, как свойство errors, которое поставляется с ValidationError.
Также вы помещаете имя поля в тип ошибки, и это избыточно, лучше использовать тот же тип ошибки, потому что в процедуре проверки ошибок вы также получите имя поля.
Итак, ваш код может выглядеть примерно так:
User.schema.path('email').validate(function(value, respond) {
User.findOne({email: value}, function(err, user) {
if(err) throw err;
if(user) return respond(false);
respond(true);
});
}, 'exists');
User.schema.path('username').validate(function(value, respond) {
User.findOne({username: value}, function(err, user) {
if(err) throw err;
if(user) return respond(false);
respond(true);
});
}, 'exists');
И затем процедура проверки ошибок:
if (err) {
switch (err.name) {
case 'ValidationError':
for (field in err.errors) {
switch (err.errors[field].type) {
case 'exists':
...
break;
case 'invalid':
...
break;
...
}
}
break;
default:
...
}
}
Если вы хотите сократить это, у вас есть различные варианты. Если у вас есть только один тип проверки, вы можете сделать это следующим образом:
if (err) {
if (err.name == 'ValidationError') {
for (field in err.errors) {
...
}
} else {
// A general error (db, crypto, etc…)
...
}
}
Минимальное выражение процедуры проверки ошибок будет аналогично тому, что вы написали в своем сообщении:
if (err) {
for (field in err.errors) {
...
}
}
Это будет работать, потому что, если ошибки не определены, он просто проигнорирует значение for. Но вы игнорируете все другие типы ошибок здесь.
Я также считаю, что эти макеты ошибок немного беспорядочны, но не ожидайте, что это изменится в ближайшем будущем.
Ответ 2
Просто напишите следующий код и наслаждайтесь.
if (err) {
console.log('Error Inserting New Data');
if (err.name == 'ValidationError') {
for (field in err.errors) {
console.log(err.errors[field].message);
}
}
}
Ответ 3
Я использую AngularJS, поэтому ngRepeat
отображает мои ошибки проверки в веб-форме. Все, что мне нужно сделать, это вернуть массив сообщений об ошибках.
Иногда Mongoose выдает ошибку, которая НЕ является ошибкой проверки, и в этом случае объект err.errors не будет присутствовать. Я регистрирую ошибку выполнения. Я все еще использую одно и то же место в веб-форме для отображения ошибки выполнения пользователю.
var makeMongooseErrorMsgArray = function(err){
var msgArray = [];
if (err.errors) { // validation errors
$.each(err.errors, function (key, val) {
msgArray.push(val.message);
});
} else if (err.message){ // should be execution error without err.errors
errLogr.log(err); // log execution errors
msgArray.push(err.message);
} else {
msgArray.push('Unknown error');
}
return msgArray;
}
Ответ 4
Я нашел это полезным, который отображает все ошибки в массиве.
Например, я отправил форму с коротким паролем и недействительным письмом.
if (err && err.name === 'ValidationError') {
err.toString().replace('ValidationError: ', '').split(',')
}
В результате этого
[ 'Please provide a valid email address',
'The password should be at least 6 characters long' ]
Если у вас есть сообщение ,
в сообщениях об ошибках, чем попытка без .split(',')
Нет необходимости в циклах for
. Убедитесь, что в вашей схеме есть сообщения об ошибках проверки. Для приведенного выше примера у меня есть
const validateEmail = email => {
const re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
return re.test(email);
};
const Schema = mongoose.Schema;
const userSchema = new Schema({
...
email: {
type: String,
trim: true,
required: 'Email address is required',
validate: [validateEmail, 'Please provide a valid email address'],
},
password: { type: String, set: encryptPassword, maxlength: [6, 'The password should be at least {MAXLENGTH} characters long'] },
...
});
Ответ 5
Почему бы вам не использовать метод validation
как описано в API?
objectToSave.validate(function(err) {
if (err) {
// handle error
}
else {
// validation passed
}
});
Ответ 6
Прочитав все эти ответы, я считаю, что лучше всего создать функцию полезности и использовать ее как таковую:
Это функция, которая обрабатывает ValidationError
путем отправки желаемого ответа клиенту с сообщениями проверки и необязательно использует console.log
для отображения сообщений в консоли.
function handleValidationError(err, res, consoleLog = false){
const messages = []
for (let field in err.errors) {
messages.push(err.errors[field].message)
consoleLog && console.log(err.errors[field].message)
}
res.status(422).json({ messages })
}
Затем в контроллере, где мы хотим обрабатывать ошибку, мы проверяем, есть ли err.name
ValidationError
, и если это так, мы используем функцию полезности сверху.
user.save((err) => {
if (err) {
if (err.name === 'ValidationError') return handleValidationError(err, res) // here
return res.status(500).json({ message: 'Error while creating new user' })
}
return res.status(201).json({ message: 'User created' })
})
Затем клиент получит в качестве ответа эхо-сигналы проверки:
curl\
-H 'Content-Type: application/json'\
-d '{"email": "foo", "password": "barbaz"}'\
http://localhost:3000/user/new
Вывод:
{"messages":["Email validation failure"]}
Ответ 7
Здесь мой единственный способ справиться с ошибкой проверки мангуста
Код по-прежнему выполняется после его готовности. Я обновлю его или вы сможете внести свой вклад в расширение моего кода.
let message = "";
let title = "Validation Error";
let code = 400;
let requiredFields = [];
for (let field in err.errors) {
let subMsg = ""
if (err.errors[field].kind === "required") {
requiredFields.push(field)
}
}
if (requiredFields.length > 0) {
message = "Following fields are required: " + requiredFields.join(", ");
} else {
message = "Unknown";
}
res.status(code).json({
status: code,
message: message,
title: title
});