Мой код - лучший способ использовать asyn c? - PullRequest
0 голосов
/ 28 марта 2020

Я пытаюсь реализовать и изучить async await functions в моем примере входа в систему, но я не знаю, является ли лучший, элегантный и чистый код. У меня есть подлые ошибки в уловах, и если мне нужно наилучшим образом реализовать const и функциональное программирование. Можете поделиться своим мнением?

app.post('/', async (req, res) => {


    try {

        const { email } = req.body.email; // destructuring

        const usuarioEncontrado = await Usuario.findOne({email: email});

        // Validate user exist
        if (!usuarioEncontrado) { // when not exist return null
            throw res.status(404).json({error: 'El usuario no existe'});
        }

        // validate user pass
        if (!bcrypt.compareSync(req.body.password, usuarioEncontrado.password)) {
            throw res.status(404).json({error: 'No match'});
        }

        const token = jwt.sign( // generate token
            {
                usuario: usuarioEncontrado 
            },
            SEED,
            {
                expiresIn: (60 * 60)
            }
        );

        res.status(200).json({ // send response
            token: token,
            usuario: usuarioEncontrado
        });

    } catch (e) { // send error

        res.status(404).json(e);

    }
}

СПАСИБО

1 Ответ

1 голос
/ 28 марта 2020

Ваш код показывает пару проблем:

  1. Вы пытаетесь отправить двойной ответ. Сначала вы бросаете res.status(404).json(...). Затем вы перехватываете это исключение и снова делаете res.status(404).json(e). Это не правильно. Если вы собираетесь отправить ответ, то просто вернитесь, не бросайте. Или просто сгенерируйте исключение, не отправляя ответ, и отправьте фактический ответ об ошибке из обработчика перехвата.

  2. Кроме того, throw res.status(404).json({error: 'No match'}); отправляет ответ, а затем выдает все, что .json() возвращает, что это, вероятно, не то, что вы хотите. Это не будет какой-либо объект ошибки.

Я предпочитаю централизовать места, в которые я отправляю ответ об ошибке, в одно место в обработчике запросов. Это удерживает вас от попыток отправить несколько ответов и просто облегчает понимание потока обработчика запросов (на мой взгляд).

Для этого я просто throw пользовательская ошибка, которая может иметь пользовательское сообщение / статус, связанный с ним, а затем перехватывать все возможные ошибки в одном месте. Вот один из способов сделать это. Класс myError может использоваться везде в вашем проекте, но не может указывать c только для одного маршрута. Идея состоит в том, что часто, когда вы throw, вы знаете в этом контексте, какой вы хотите статус и сообщение, чтобы вы устанавливали это в пользовательском объекте Error и затем могли использовать эту информацию в перехвате. Затем улов должен определить, есть ли у вас пользовательская ошибка или просто обычная ошибка. Во-первых, у меня есть подкласс Error многократного использования, который позволяет мне выдавать не только сообщение, но и значение состояния.

// reusable error class that contains a status in addition to the message
class MyError extends Error {
    // this static method saves having to compare if it's a custom error object or not
    // every time we use this
    static sendError(res, e, status = 500) {
        if (e instanceof MyError) {
            e.sendError(res);
        } else {
            res.sendStatus(status);
        }
    }
    constructor(msg, status = 500) {
        // allow calling with or without new
        if (!(this instanceof MyError)) {
            return new MyError(msg, status);
        }
        super(msg);
        this.status = status;
    }
    sendError(res) {
        res.status(this.status).send(this.message);
    }
}

И затем вот как вы используете это в своем коде и централизует отправку статус ошибки.

app.post('/', async (req, res) => {

    try {

        const { email } = req.body.email; // destructuring

        const usuarioEncontrado = await Usuario.findOne({email: email});

        // Validate user exist
        if (!usuarioEncontrado) { // when not exist return null
            throw MyError('El usuario no existe', 404);
        }

        // validate user pass
        if (!bcrypt.compareSync(req.body.password, usuarioEncontrado.password)) {
            throw MyError('No Match', 404);
        }

        const token = jwt.sign( // generate token
            {
                usuario: usuarioEncontrado 
            },
            SEED,
            {
                expiresIn: (60 * 60)
            }
        );

        res.status(200).json({ // send response
            token: token,
            usuario: usuarioEncontrado
        });

    } catch (e) { // log and send error response
        // e may be either MyError or some other system generated Error
        console.log(e);
        MyError.sendError(res, e);
    }
}
...