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:
- Crear un envoltorio para el método
query
usando una Promesa.
- 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.