Подтвердить что ты не робот

Лучший способ проверить ошибку проверки мангуста

У меня есть две функции 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) { ... }

Это отвратительно.

4b9b3361

Ответ 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
});