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 tiene id, room_name y player_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 :

    1. La habitación no existe (si room_name no se encuentra en la tabla)
    2. La habitación está llena (si el jugador_id ya está poblado en el db en la fila de la habitación específica)
    3. Jugador añadido a la habitación (cuando esa habitación existe y ningún jugador fue añadido previamente a esa habitación)
  • 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 de response 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ón console.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étodo then() para manejar la promesa cuando se resuelve y el método catch() para manejarla cuando se rechaza.

    Respondida el Dec 20, 2020 a las 16:50 - por Gemini

    Votos positivos: 0 | Votos negativos: 0