2

Tengo un proyecto web y quiero guardar datos en mysql, con este código

router.post('/add',async(req,res) =>{
   const {title, url, description } = req.body;
    const newLink={
        title,
        url,
        description
        //ALMACENA ESOS DATOS EN LA VARIABLE NEWLINK
    };
    await pool.query('INSERT INTO links set ?',[newLink]); //almacenando datos

    res.send('recibido');

});

Pero me marca error de:

"(node:7300) 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(). (rejection id: 3)"

Desde que agregue el

pool.query

me marca error y ando usando express ** pool es la variable para llamar a la Base de datos.

Les agradecería mucho su ayuda c:

Luis Neyra
  • 21
  • 1

1 Answers1

1

El problema es que no estás realizando correctamente el proceso para ejecutar la función de forma asíncrona. Para solucionarlo tienes dos opciones:

  1. Crear un envoltorio para el método query usando una Promesa.
  2. Usar una función callback tal como sugiere la documentación de la librería mysql.

Usando Promesas

En primer lugar, debemos entender que el método query es un método asíncrono, por lo tanto podemos manejarlo usando async/await que es lo que estás intentando. Sin embargo, si el método falla lanzará (throw) algún error, y si no capturamos dicho evento entonces Node nos mostrará un mensaje de error en donde nos dirá que no hemos capturado dicho error.

Sin entrar mucho en detalles, una promesa devolverá un resultado resolve (resuelto) o reject (rechazado), dependiendo del resultado de los procesos o tareas ejecutadas.

Dado que el método query(), usa el antiguo sistema de funciones callback (no devuelve una promesa), debemos crear un envoltorio sobre dicho método para poder usar correctamente nuestra promesa.

Una forma de hacerlo es crear una función async que devuelva una promesa, de la siguiente forma:

const insertLinks = async (newLinks) => {
    return new Promise((resolve, reject) => {
        const queryString = 'INSERT INTO links set ?';
        pool.query(queryString, [newLinks], (error, results, fields) => {
            if(error) return reject(error); // <= si el proceso falla llamamos a reject y le pasamos el objeto error como argumento
            const data = {results, fields};
            return resolve(data); // <= si el proceso es exitoso llamamos a resolve y le pasamos el objeto data como argumento
        });
    }
}

Con esto ya tenemos una función envoltorio para el método query, en este caso es una función llamada insertLinks, para ser coherentes con el trabajo realizada por la misma.

En tu controlador (o en tu router) la podrías usar de la siguiente manera:

router.post('/add',async(req,res) =>{
    const {title, url, description } = req.body;
    const newLink={
        title,
        url,
        description
        //ALMACENA ESOS DATOS EN LA VARIABLE NEWLINK
    };
    // Toda promesa debe ser ejecutada en un bloque try catch
    // ya que si se devuelve reject, el mismo sera capturado por catch
    try {
        const data = await insertLinks(newLink); // almacenamos el resultado por si queremos trabajar con el mismo
        return res.status(200).send('recibido');
    } catch(err) {
        console.log(err);
        return res.status(500).send('error');
    }
});

Con esto podremos trabajar sin problemas usando async/await.

Usando una función callback

Tal como lo plantea la documentación de la librería mysql, puedes pasar como último argumento al método query una función callback que realizará los procesos de acuerdo al resultado de la consulta.

Una forma en la que podrías realizar el proceso es la siguiente:

router.post('/add', (req,res) =>{ // <- La función middleware ya no es async
    const {title, url, description } = req.body;
    const newLink={
        title,
        url,
        description
        //ALMACENA ESOS DATOS EN LA VARIABLE NEWLINK
    };
    pool.query('INSERT INTO links set ?',[newLink], (error, results, fields) => { // <- usamos una función callback
        if(error) { // <- Si ocurre un error en la consulta
            console.log(error); // <- mostramos error por consola
            return res.status(500).send('error'); // <- enviamos mensaje al cliente
        }
        // ...
        // hacemos algo con los resultados (si lo necesitamos)
        // ...
        return res.status(200).send('recibido'); // <- enviamos mensaje al cliente
    });
});

Como puedes apreciar en el código, no usamos async/await, en vez de eso, usamos el método query pasando como último argumento una función callback, y es dentro de dicha función que usaremos el objeto response para enviar el resultado de nuestra consulta hacia el cliente.

Espero que esto te ayude a resolver el problema y aclare tus dudas.

Mauricio Contreras
  • 13,660
  • 3
  • 18
  • 40
  • Muchas gracias, yo no lo he preguntado pero a mi me ha servido de mucho!! Un saludo. – jov Aug 28 '20 at 00:40