Как получить результат mysql.query снаружи?

Пишу API регистрации/авторизации на node+express. Роут /registration должен в любом случае вернуть json-объект такого вида:

{
    "registered": false, // Есть или нет такой email в базе
    "error": false, // Есть ли ошибки валидации
    "message": "" // Пишем сообщение что именно не так
}

На клиенте я буду читать этот ответ и соответствующим образом реагировать. Данный объект формируется следующим кодом:

const express = require('express')
const router = express.Router()
const db = require('./dbConnection')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const { isEmail } = require('./emailValidator.js')

router.post('/registration', (req, res) => {
    const email = req.body.email.toLowerCase()

    // Основа будущего json-объекта с ответом
    let registered = false
    let error = false
    let message = ''

    // Валидация email
    if (email == '') {
        // Если email пустой
        error = true
        message = 'Email is empty'
    } else if (!isEmail(email)) {
        // Если email не корректен
        error = true
        message = 'Email is incorrect'
    }

    // Проверим, существует ли такой email в базе данных
    db.query(`SELECT * FROM users WHERE email = ${db.escape(email)}`, (err, result) => {
        if (result.length) {
            // Если что-то вернулось, значт email уже зарегистрирован
            // Меняем данные ответа
            registered = true
            error = true
            message = 'This email already in use'
            // Проблема здесь. Переменные недоступны снаружи, return не помогает.
        } else {
            // Если email ранее не регистрировался, пишем его в базу
            // registered, error, message остаются дефолтными
        }
    })

    // Возвращаем финальный объект с ответом
    const response = { registered, error, message }
    res.status(200).json(response)
})

В коде я написал, откуда не могу получить переменные для внесения их в json-объект ответа. Как их получить снаружи?


Ответы (2 шт):

Автор решения: Oliver Patterson

По сути вам нужно это все завернуть в промис.

const express = require('express')
const router = express.Router()
const db = require('./dbConnection')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const { isEmail } = require('./emailValidator.js')

router.post('/registration',  async (req, res) =>
{
    const email = req.body.email.toLowerCase()

    // Основа будущего json-объекта с ответом
    let registered = false
    let error = false
    let message = ''

    // Валидация email
    if (email == '')
    {
        // Если email пустой
        error = true
        message = 'Email is empty'
    }
    else if (!isEmail(email))
    {
        // Если email не корректен
        error = true
        message = 'Email is incorrect'
    }
    else
    {
        // Проверим, существует ли такой email в базе данных
        const query = new Promise((resolve, reject) =>
        {
            db.query(`SELECT * FROM users WHERE email = ${db.escape(email)}`, (err, result) =>
            {
                if (err)
                {
                    reject(err);
                    return;
                }
    
                if (result.length)
                {
                    // Если что-то вернулось, значт email уже зарегистрирован
                    // Меняем данные ответа
    
                    resolve({registered: true, error: true, message: 'This email already in use'})
                }
                else
                {
                    // Если email ранее не регистрировался, пишем его в базу
                    // registered, error, message остаются дефолтными
                }
            })
        });
    
        try
        {
            ({registered, error, message}) = await query;
        }
        catch (err)
        {
            console.error(err);
        }
    }

    // Возвращаем финальный объект с ответом
    const response = { registered, error, message }
    res.status(200).json(response)
})

→ Ссылка
Автор решения: vegasmoscow

Получилось сделать через коллбэки:

const express = require('express')
const router = express.Router()
const db = require('./dbConnection')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const { isEmail } = require('./emailValidator.js')

router.post('/registration', (req, res) => {
    const email = req.body.email.toLowerCase()
    const password = req.body.password
    let registered = false
    let error = false
    let message = ''

    // Validate email
    if (email == '') {
        // Is email empty
        registered = false
        error = true
        message = 'Email is empty'
        res.status(400).json({ registered, error, message })
        return
    } else if (!isEmail(email)) {
        // Is email correct
        registered = false
        error = true
        message = 'Email is incorrect'
        res.status(400).json({ registered, error, message })
        return
    }

    // Validate password
    if (password == '') {
        // Is password empty
        registered = false
        error = true
        message = 'Password is empty'
        res.status(400).json({ registered, error, message })
        return
    }

    // Register new user
    db.query(`SELECT * FROM users WHERE email = ${db.escape(email)}`, (err, result) => {
        if (result.length) {
            // If email already in use
            registered = false
            error = true
            message = 'Email is already in use'
            res.status(400).json({ registered, error, message })
        } else {
            // Email is available
            bcrypt.hash(password, 10, (err, hash) => {
                if (err) {
                    // If password not hashed
                    registered = false
                    error = true
                    message = 'Password was not hashed'
                    res.status(500).json({ registered, error, message })
                    return
                } else {
                    // Add to database email and hashed password
                    db.query(`INSERT INTO users (email, password) VALUES (${db.escape(email)}, ${db.escape(hash)})`, (err, result) => {
                        if (err) {
                            // If query is not success
                            registered = false
                            error = true
                            message = 'Some problems with data base'
                            res.status(500).json({ registered, error, message })
                            return
                        } else {
                            registered = true
                            error = false
                            message = 'New user creted'
                            res.status(200).json({ registered, error, message })
                            return
                        }
                    })
                }
            })
        }
    })
})
→ Ссылка