1

Tengo este query, pero no logro alcanzar el total que declaro, cada que trato de hacerle un console.log(unitusedCount[0].total) me da 0 t algo me dice que es en la forma en la que lo trato de cachar.

    router.post('/tc-assign/',async (req,res)=>{
    const {id_user, id_project , id_tc,id_client,amount} = req.body;

    console.log(id_user,id_project,id_tc,id_client,amount);




    const unitusedCount = await pool.query('SELECT COUNT(*) as total FROM tc_u where status = 1 and id_client = ?',[id_client]);



    console.log(unitusedCount[0].total);
});
E.Rawrdríguez.Ophanim
  • 1,185
  • 5
  • 26
  • 72

1 Answers1

0

El problema es la forma en que capturas el resultado devuelto por la consulta. Además en tu código no veo que uses un bloque try/catch para trabajar con las Promesas.

Según la documentación de mysql2 (asumo que es la librería que consumes), cuando usas una función tipo async de envoltorio para trabajar con Promesas, debes capturar los datos de la siguiente forma:

const [rows, fields] = await pool.query('SELECT COUNT(*) as total FROM tc_u where status = 1 and id_client = ?',[id_client]);

Los nombres de las variables rows y fields los puedes cambiar a gusto, pero siempre debes capturar 2 valores.

Así, rows es un Array con el resultado (o resultados) de tu consulta, y fields es un Array que contiene meta datos relevantes al resultado de la consulta.

Fíjate que en la respuesta de la Promesa no hay un objeto de error, es por ello que debemos usar try/catch.

Así tu código podría verse parecido al siguiente:

router.post('/tc-assign/', async (req,res)=>{
  const { id_user, id_project, id_tc, id_client, amount } = req.body;
  console.log(id_user,id_project,id_tc,id_client,amount);
  try {
    const [rows, fields] = await pool.query('SELECT COUNT(*) as total FROM tc_u where status = 1 and id_client = ?', [id_client]);
    console.log(rows[0].total); // Una consulta COUNT(*) devuelve sólo una fila en el resultado (por eso usamos rows[0])
    ...
  }
  catch(e) { // <= aquí capturamos un eventual error en la consulta
    console.error(e.message); // mostramos el error
    ...
  }
});

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

EDICIÓN

Dado que comentas que usas la librería mysql, la cual usa el antiguo sistema de funciones callback para manejar los procesos asíncronos, debes crear un envoltorio para tu método pool.query(), el cuál devolverá una Promesa que podrás usar en tu código.

En la respuesta a esta pregunta: Error en almacenar datos con mysql y Node.js, explico básicamente este mismo proceso y además explico cómo hacerlo sin usar Promesas.

Un envoltorio podría ser el siguiente:

const doQuery = (query, params) => {
  return new Promise((resolve, reject) => {
    pool.query(query, params, (error, rows, fields) => {
      if(error) {
        return reject(error);
      }
      return resolve([rows, fields]);
    });
  });
}

Además debes crear la cadena con la consulta y el array de parámetros:

const query = 'SELECT COUNT(*) as total FROM tc_u where status = 1 and id_client = ?';
const params = [id_client];

Luego, escribimos todo esto dentro del método post de tu objeto router:

router.post('/tc-assign/', async (req,res)=>{
  const { id_user, id_project, id_tc, id_client, amount } = req.body;
  console.log(id_user,id_project,id_tc,id_client,amount);
  // creamos la consulta y los parámetros
  const query = 'SELECT COUNT(*) as total FROM tc_u where status = 1 and id_client = ?';
  const params = [id_client];
  // creamos la función envoltorio
  const doQuery = (query, params) => {
    return new Promise((resolve, reject) => {
      pool.query(query, params, (error, rows, fields) => {
        if(error) {
          return reject(error);
        }
        return resolve([rows, fields]);
      });
    });
  }
  try {
    // usamos la función envoltorio
    const [rows, fields] = await doQuery(query, params);
    console.log(rows[0].total); // Una consulta COUNT(*) devuelve sólo una fila en el resultado (por eso usamos rows[0])
    ...
  }
  catch(e) { // <= aquí capturamos un eventual error en la consulta
    console.error(e.message); // mostramos el error
    ...
  }
});

Con esto ya puedes usar asyn/await con la librería mysql.

Lo ideal es crear un módulo que puedas importar en cada lugar donde necesites usar el envoltorio, de esta forma no necesitas repetir el código.

Mauricio Contreras
  • 13,660
  • 3
  • 18
  • 40
  • me da 'Cannot read property 'total' of undefined' ya probè con `(fields.total)` – E.Rawrdríguez.Ophanim Sep 21 '19 at 16:20
  • estoy usando mysql no mysql2 – E.Rawrdríguez.Ophanim Sep 21 '19 at 16:31
  • Entonces no puedes usar promesas a menos que crees tu propia implementación. La librería `mysql` usa el antiguo sistema de `callbacks` y no da soporte para usar `async/await`. En [esta](https://es.stackoverflow.com/questions/266927/error-en-almacenar-datos-con-mysql-y-node-js/267107#267107) respuesta ofrezco una solución, sin embargo editaré esta respuesta para añadir cómo lo debes hacer. Saludos – Mauricio Contreras Sep 21 '19 at 16:46
  • acabo de notar que siempre me devuelve 0 , si hago el mismo query en un ui de mysql me da la verdadera suma – E.Rawrdríguez.Ophanim Sep 21 '19 at 17:07
  • He implementado el código de mi respuesta, uso Express `4.17.1`, Node `12.8.0` y mysql `2.17.1`, mi Servidor MySQL es `14.14 Distrib 5.7.27, for Linux (x86_64)`. El resultado es el esperado al realizar la consulta. Saludos – Mauricio Contreras Sep 21 '19 at 17:34