Respuesta de la consulta Express MySql sin definir
Soy nuevo en Node.js y Express. Tengo un fondo PHP en el lado servidor, sólo para que entiendas cómo entiendo el lado backend.
Voy a explicar en palabras lo que quiero lograr y después de eso voy a pegar un ejemplo mínimo de código de mi proyecto, la parte que no funciona como se esperaba.
Descripción:
Tengo una mesa llamada
room
que tieneid
,room_name
yplayer_id
. Esta tabla ya está poblada con 1 fila utilizando:INSERT INTO room (id, room_name, player_id) VALUES (1, "room1", "")
. En otras palabras tengo una habitación que tiene alguna información perdida sobre el jugador que se unió a esa habitación.Tengo una función llamada
addPlayerToRoom(id_player, room_name)
que se ejecuta cuando quiero añadir un jugador a una habitación. Esta función puede devolver 3 tipos de respuestas :- La habitación no existe (si
room_name
no se encuentra en la tabla) - La habitación está llena (si el jugador_id ya está poblado en el db en la fila de la habitación específica)
- Jugador añadido a la habitación (cuando esa habitación existe y ningún jugador fue añadido previamente a esa habitación)
- La habitación no existe (si
Quiero devolver uno de estos 3 estatus y consola. log them but everything I do, I get undefinited even though the code works for each case. Si consola logré la respuesta antes del regreso obtengo la buena respuesta en la consola. También todo funciona en el db también, lo que significa que el jugador se añade si la habitación está vacía.
Código:
const response = addPlayerToRoom(7, "room1"); // 7 is the player_id which is any random number
console.log(response) // => undefined (why I get undefined ???)
function addPlayerToRoom(id_player, room_name) {
let sql1 = "SELECT * FROM room WHERE room_name = ?";
let pre1 = [room_name];
sql1 = mysql.format(sql1, pre1);
// fetch the room in the db
connection.query(sql1, function (err1, rows1) {
// check if room exists
if (rows1.length > 0) {
// check if the room is full
if (row1[0].player_id !== '') {
return "Room is full !"
}
else {
let sql2 = 'UPDATE room SET player_id = ? WHERE name = ?';
let pre2 = [id_player, room_name];
sql2 = mysql.format(sql2, pre2);
connection.query(sql2, function (err2, rows2) {
return "Player added to room !"
});
}
}
else {
return "Room does not exist !"
}
}
}
Lo que creo en este punto es que la consola. inicia el registro antes de que la función se ejecute porque si agrego cualquier consola al azar. log in the function it gets pasted in the console after I get the unfini pasted... which means to me that it does not wait for the function execution.
Esto es extraño para mí cuando pienso en PHP donde no experimenté este tipo de problemas. ¿Esto significa que cada vez que hago una pregunta de Mysql debería usar una promesa o algo así? Traté de algo pero sin éxito.
¿Alguna idea cómo resolver esto? Gracias.
Pregunta hecha hace 3 años, 5 meses, 3 días - Por stackscripter
2 Respuestas:
-
El problema que estás experimentando se debe a la naturaleza asíncrona de Node.js y las consultas a la base de datos. En tu código actual, estás intentando devolver un valor directamente desde la función
addPlayerToRoom
, pero las consultas a la base de datos se realizan de forma asíncrona, por lo tanto, el valor deresponse
se está devolviendo antes de que la consulta a la base de datos finalice.Para resolver este problema, puedes utilizar promesas o callbacks para manejar correctamente el flujo asíncrono de las consultas a la base de datos. Aquí te dejo un ejemplo de cómo modificar tu código para utilizar promesas:
javascript function addPlayerToRoom(id_player, room_name) { return new Promise((resolve, reject) => { let sql1 = "SELECT * FROM room WHERE room_name = ?"; let pre1 = [room_name]; sql1 = mysql.format(sql1, pre1); // fetch the room in the db connection.query(sql1, function (err1, rows1) { if (err1) { reject(err1); } else { if (rows1.length > 0) { if (rows1[0].player_id !== '') { resolve("Room is full !"); } else { let sql2 = 'UPDATE room SET player_id = ? WHERE name = ?'; let pre2 = [id_player, room_name]; sql2 = mysql.format(sql2, pre2); connection.query(sql2, function (err2, rows2) { if (err2) { reject(err2); } else { resolve("Player added to room !"); } }); } } else { resolve("Room does not exist !"); } } }); }); } addPlayerToRoom(7, "room1") .then(response => { console.log(response); }) .catch(error => { console.error(error); });
En este código, la función
addPlayerToRoom
ahora devuelve una promesa que se resolverá con el mensaje correspondiente una vez que la consulta a la base de datos se complete. Luego, puedes usar.then()
para manejar la respuesta exitosa y.catch()
para manejar cualquier error que pueda ocurrir durante la ejecución de la consulta.Con este enfoque, podrás manejar de manera adecuada el flujo asíncrono de las consultas a la base de datos en Node.js. Espero que esta explicación y el ejemplo te ayuden a resolver tu problema. ¡Déjame saber si necesitas más ayuda!
Respondida el Dec 20, 2020 a las 16:45 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
El problema que estás experimentando se debe a la naturaleza asíncrona de las operaciones de la base de datos en Node.js. Cuando llamas a
connection.query
, la función devuelve inmediatamente el control al código de llamada sin esperar a que se complete la consulta. Esto significa que tu código continúa ejecutandose y llega a la instrucciónconsole.log(response)
antes de que se haya recibido la respuesta de la base de datos.Para resolver este problema, debes utilizar una función de devolución de llamada o una promesa para esperar a que se complete la consulta antes de intentar acceder a la respuesta. Aquí tienes un ejemplo modificado de tu código que utiliza una función de devolución de llamada:
javascript function addPlayerToRoom(id_player, room_name, callback) { let sql1 = "SELECT FROM room WHERE room_name = ?"; let pre1 = [room_name]; sql1 = mysql.format(sql1, pre1); // fetch the room in the db connection.query(sql1, function (err1, rows1) { // check if room exists if (rows1.length > 0) { // check if the room is full if (row1[0].player_id !== '') { callback("Room is full !"); } else { let sql2 = 'UPDATE room SET player_id = ? WHERE name = ?'; let pre2 = [id_player, room_name]; sql2 = mysql.format(sql2, pre2); connection.query(sql2, function (err2, rows2) { callback("Player added to room !"); }); } } else { callback("Room does not exist !"); } } } addPlayerToRoom(7, "room1", function(response) { console.log(response); });
En este ejemplo, la función
addPlayerToRoom
toma un tercer argumento, que es una función de devolución de llamada. Cuando se completa la consulta de la base de datos, se llama a la función de devolución de llamada con la respuesta como argumento. El código de llamada puede entonces utilizar la respuesta para registrarla en la consola o realizar cualquier otra acción necesaria.También puedes utilizar promesas para manejar las operaciones de la base de datos de forma asíncrona. Aquí tienes un ejemplo utilizando promesas:
javascript function addPlayerToRoom(id_player, room_name) { return new Promise((resolve, reject) => { let sql1 = "SELECT FROM room WHERE room_name = ?"; let pre1 = [room_name]; sql1 = mysql.format(sql1, pre1); // fetch the room in the db connection.query(sql1, function (err1, rows1) { // check if room exists if (rows1.length > 0) { // check if the room is full if (row1[0].player_id !== '') { reject("Room is full !"); } else { let sql2 = 'UPDATE room SET player_id = ? WHERE name = ?'; let pre2 = [id_player, room_name]; sql2 = mysql.format(sql2, pre2); connection.query(sql2, function (err2, rows2) { resolve("Player added to room !"); }); } } else { reject("Room does not exist !"); } } }); } addPlayerToRoom(7, "room1").then(response => { console.log(response); }).catch(error => { console.log(error); });
En este ejemplo, la función
addPlayerToRoom
devuelve una promesa. Cuando se completa la consulta de la base de datos, la promesa se resuelve con la respuesta o se rechaza con un error. El código de llamada puede entonces utilizar el métodothen()
para manejar la promesa cuando se resuelve y el métodocatch()
para manejarla cuando se rechaza.Respondida el Dec 20, 2020 a las 16:50 - por Gemini
Votos positivos: 0 | Votos negativos: 0