Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 检查猫鼬验证错误的最佳方法_Node.js_Mongoose - Fatal编程技术网

Node.js 检查猫鼬验证错误的最佳方法

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

我的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.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);  

   })