#javascript #node.js #mongodb #express #mongoose
Вопрос:
Я хочу использовать «уникальный валидатор мангуста» для более легкой обработки ошибки проверки Монго. Проблема возникает, когда я пытаюсь вызвать ошибку проверки, и она даже не входит в мой пользовательский обработчик ошибок. Любая другая ошибка работает правильно, но не эта.
Я просто хочу, чтобы валидатор отправил ответ JSON, чтобы клиентское приложение могло видеть, какое поле неверно/не уникально.
handleErrors.js
const ERROR_HANDLERS = {
// Example handler that actually works.
JsonWebTokenError: (res) => res.status(401).json({ error: 'Token missing or invalid' }),
// Handler that is not working
ValidationError: (res, { message }) => res.status(409).json({ error: message }),
};
module.exports = (err, req, res, next) => {
const handler = ERROR_HANDLERS[err.name];
handler(res, err);
};
User.js
const { Schema, model } = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const UserSchema = new Schema({
username: {
type: String,
unique: true,
uniqueCaseInsensitive: true,
trim: true,
required: true,
},
email: {
type: String,
unique: true,
uniqueCaseInsensitive: true,
lowercase: true,
trim: true,
required: true,
},
passwordHash: {
type: String,
trim: true,
required: true,
},
});
UserSchema.plugin(uniqueValidator);
module.exports = {
User: model('User', UserSchema),
};
index.js
app.use(appRouter);
app.use('/api/users', userRouter);
app.use(notFound);
app.use(handleErrors);
userRouter.js
const usersRouter = require('express').Router();
const userController = require('../controllers/userController');
usersRouter.get('/', userController.listAll);
usersRouter.post('/', userController.create);
module.exports = usersRouter;
userController.js
create: async (req, res) => {
const { body } = req;
const passwordHash = await bcrypt.hash(body.password, 10);
const user = new User({
...body,
passwordHash,
});
const savedUser = await user.save();
res.status(201).send(savedUser);
},
Вывод консоли при срабатывании ошибки проверки
DB connected
(node:8728) UnhandledPromiseRejectionWarning: ValidationError: User validation failed: username: Error, expected `username` to be unique. Value: `user2`, email: Error, expected `email` to be unique. Value: `user2@email.com`
at model.Document.invalidate (xnode_modulesmongooselibdocument.js:2704:32)
at xnode_modulesmongooselibdocument.js:2524:17
at xnode_modulesmongooselibschematype.js:1241:9
at processTicksAndRejections (internal/process/task_queues.js:75:11)
(node:8728) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:8728) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Комментарии:
1. Можете ли вы добавить в свой
userRouter.js
файл также выводconsole.log(err)
2. @TusharGupta-любопытный тушар готов! userRouter.js добавлено. Я не добавил console.log(err), кстати, потому что он просто не будет запускаться в обработчике ошибок, когда ошибка является ошибкой проверки, но это происходит, когда это другой error.name. Я имею в виду, что если ошибка является ошибкой проверки, она даже не войдет в обработчик, а просто выведет предупреждение о необработанных запросах на консоль.
3. Пожалуйста, добавьте код
userController.create
функции .4. @TusharGupta-любопытно, что сделано
Ответ №1:
Оберните свой const savedUser = await user.save();
блок в try-catch, чтобы зафиксировать ошибку и обработать ошибку в блоке catch.
create: async (req, res, next) => {
const { body } = req;
const passwordHash = await bcrypt.hash(body.password, 10);
const user = new User({
...body,
passwordHash,
});
try {
const savedUser = await user.save();
res.status(201).send(savedUser);
} catch (error) {
console.log(error);
next(error);
// throw error; // you can throw error
// res.status(422).send({ 'message': 'Validation error' }); // handle your error here
}
},
Комментарии:
1. Конечно, но я хочу обработать ошибку с помощью модуля ERROR_HANDLER, вызовет ли это решение это промежуточное программное обеспечение?
2.@JMRBDev добавляй
next
и звониnext(error);
expressjs.com/en/guide/error-handling.html