0

The problem is that when I make a POST call to /login, the const user gets assigned undefined even though getUser() always returns the same value. The call console.log(getUser()); at the end of the file works fine.

I simplified and unified the code.

index.js

const express = require("express");
const secret = "123456789";
const jwt = require("jsonwebtoken");
const mariadb = require('mariadb');
const pool = mariadb.createPool({
    host: 'localhost',
    user: 'root',
    password: '',
    database: "test",
    connectionLimit: 5
});

const app = express();
const port = process.env.PORT || 3000;

async function getUser()  {
    let conn;
    try {
        conn = await pool.getConnection();
        const rows = await conn.query("SELECT 'John' as username");
        console.log(rows); // Prints [ { username: 'John' } ]
        return rows;
    } catch (err) {
        throw err;
    } finally {
        if (conn) return conn.end();
    }
}

app.post('/login', async (req, res) => {
    const user = await getUser();

    console.log(user); // Prints undefined
    if (!user) {
        return res.status(401).send({
            success: false,
            msg: "Usuario o contraseña incorrecta"
        })
    }

    if (user) {
        const payload = {
            id: user.email,
            dni: user.dni
        };

        const token = jwt.sign(payload, secret, { expiresIn: "1d" });
        return res.status(200).send({
            success: true,
            token: 'Bearer ' + token
        })
    }
});

app.listen(port, () => {
    console.log(`Listening at http://localhost:${port}`);
});

console.log(getUser());

package.json

{
  "dependencies": {
    "express": "^4.18.2",
    "jsonwebtoken": "^9.0.0",
    "mariadb": "^3.1.1",
    "nodemon": "^2.0.22",
    "passport": "^0.6.0"
  }
}

I played around with the async/await, looked through the documentation and searched similar problems but can't find what is wrong.

FMR7
  • 23
  • 4

2 Answers2

3

The problem in your code is that you have a return statement in the finally block.

When you have a return in your finally block, the returns in try or catch blocks do not get executed. So, your function returns the result of return conn.end();.

Remove the return word from the finally block and the function should return what you expect.

notrev
  • 665
  • 1
  • 5
  • 16
  • It works. But why when I made the call `console.log(getUser());` at the end of the code doesn't returns `undefined` ? – FMR7 Mar 24 '23 at 09:50
  • `getUser()` is an async function and it returns a `Promise` that resolves to something. When you called `console.log(getUser());` you are not awaiting for the resolution of the promise, so you get a `Promise` object. To get the resolution, you need to do like this: `console.log(await getUser());` – notrev Mar 24 '23 at 10:03
  • When I call `console.log(getUser());` at the end of the file it returns `[ { username: 'John' } ]`, even tho im not using `await`. Thats what I don't get, it returns different values depending where I call it from. – FMR7 Mar 24 '23 at 10:06
0

MDN finally-block documentation:

Control flow statements (return, throw, break, continue) in the finally block will "mask" any completion value of the try block or catch block. In this example, the try block tries to return 1, but before returning, the control flow is yielded to the finally block first, so the finally block's return value is returned instead.

function doIt() {
  try {
    return 1;
  } finally {
    return 2;
  }
}

doIt(); // returns 2

It is generally a bad idea to have control flow statements in the finally block. Only use it for cleanup code.

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52