Node.js 检查猫鼬验证错误的最佳方法
我的usermodel有两个函数Node.js 检查猫鼬验证错误的最佳方法,node.js,mongoose,Node.js,Mongoose,我的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'); 对于用户名 User.sc
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');
对于用户名
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' } } }
电子邮件路径的错误与此类似。有没有比下面更聪明的方法来检查这些错误
if (err && err.errors && err.errors.username) { ... }
这有点难看。为什么不使用验证方法呢
从技术上讲,您必须首先检查错误名称,因为并非所有错误都以相同的方式处理。然后,必须根据错误名称检查特定属性,如ValidationError附带的errors属性
此外,您还将字段名放在错误类型中,这是多余的,最好使用相同的错误类型,因为在错误检查过程中,您还将获得字段名
因此,您的代码可以是:
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) {
case err instanceof mongoose.Error.ValidationError:
for (field in err.errors) {
switch (err.errors[field].type) {
case 'exists':
...
break;
case 'invalid':
...
break;
...
}
}
break;
default:
...
}
}
如果你想缩短这个时间,你有多种选择。如果您只有一种类型的验证,您可以这样做:
if (err) {
if (err instanceof mongoose.Error.ValidationError) {
for (field in err.errors) {
...
}
} else {
// A general error (db, crypto, etc…)
...
}
}
错误检查过程的最小表达式类似于您在文章中所写的内容:
if (err) {
for (field in err.errors) {
...
}
}
这将起作用,因为如果没有定义错误,它将忽略for。但是您忽略了这里的所有其他错误类型
我还认为这些错误布局有点混乱,但不要指望在不久的将来会发生变化。只需编写以下代码即可
if (err) {
console.log('Error Inserting New Data');
if (err.name == 'ValidationError') {
for (field in err.errors) {
console.log(err.errors[field].message);
}
}
}
我发现这有助于显示数组中的所有错误
例如,我提交了一个带有短密码和无效电子邮件的表单
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' ]
如果错误消息中有逗号,
,请尝试不使用。拆分(',')
对于
循环,不需要。确保架构中有验证错误消息。对于上面的例子,我有
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'] },
...
});
我使用AngularJS,因此ngRepeat
在web表单上显示我的验证错误。我所需要做的就是返回一组错误消息
有时Mongoose会抛出一个不是验证错误的错误,在这种情况下,err.errors对象将不存在。我记录执行错误。我仍然使用web表单上的相同点向用户显示执行错误
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;
}
通过阅读所有这些答案,我认为创建效用函数并重用它是最好的:
此函数通过向客户端发送所需的响应和验证消息来处理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"]}
这里是我处理mongoose验证错误的独特方法
代码仍在进行中,一旦准备就绪,我将更新它,或者您可以帮助扩展我的代码
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
});
方法#1
我对这种方法的最佳猜测是使用基于承诺的回报的广义验证器,
希望这能对以后有所帮助
function validateDoc(model,fieldName) {
return new Promise((resolve, reject) => {
model.validate(err => {
if (err) {
return reject(err.errors[fieldName]);
} else {
return resolve(model);
}
});
})
}
// Access error message in catch() or get the validated doc in then()
validateDoc(model,fieldName)
.then((model) => console.log(model))
.catch((message) => console.warn(message))
方法#2
const userSchema = new Schema({
name: {
type:String,
required:[true,'Name is required.'],
validate:{
validator:(name) => { name.length <= 2 }
message:'Name must be longer than two characters'
}
}
})
const User = mongoose.model('user',userSchema)
此方法称为pre-save,如果违反了验证规则,save将中止,错误将返回到回调。
因此,这基本上就是我正在做的事情。我遇到的问题是在没有太多麻烦的情况下处理err
。ValidationError是一般错误,由其他几个模块抛出,每个模块具有不同的格式和/或属性。最好是明确地在错误检查过程中检查mongoose.Error.ValidationError的errinstanceof mongoose.Error
。这并不是您希望代码中的任何地方都能看到的东西,但它将是一个很好的帮助函数。
const userSchema = new Schema({
name: {
type:String,
required:[true,'Name is required.'],
validate:{
validator:(name) => { name.length <= 2 }
message:'Name must be longer than two characters'
}
}
})
const User = mongoose.model('user',userSchema)
const newUser = new User({ name: undefined });
newUser.save().catch( ( { errors } ) => {
let errorBag = [];
Object.keys(errors).forEach((fieldName) => {
errorBag.push({ [fieldName]:errors[fieldName].message })
});
// All the errors with the **fieldName** and **errorMessages**
console.log(errorBag);
})