Узел и MongoDB с экспресс-обработчиком ошибок и обработчиком ошибок Мангуста с использованием «уникального валидатора мангуста»

#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