0

I am new to async/await and I'm trying to set a 'user'-constant as the return value of a MySQL query in Node.js. However, the constant does not wait for the return value of the function. How do I use async and await to set 'user' to the return value of the SQL query?

// Should return a user object
const getUserByUsername = async (username, db) => {

  const QUERY = `SELECT * FROM ${table_name} WHERE username = '${username}'`;
    
    const user = await db.query(QUERY,
      async (err, result) => {

        if (!err) {

          console.log("name in SQL function: " + result[0].username);
          return await result[0];

        } else {
          console.log(err);
        }
      }
    );
    return user;
};

// Does stuff with the user object
const authenticateUser = async (username, password, done) => {

    const user = await getUserByUsername(username, db);
    console.log("name in main function: " + user.username);

    // Trying to do stuff with the user object...
  }

What I get in the terminal:

name in main function: undefined

UnhandledPromiseRejectionWarning: Error: data and hash arguments required
at Object.compare
at /app/node_modules/bcrypt/promises.js:29:12
at new Promise (<anonymous>)
at Object.module.exports.promise
etc.....


name in SQL function: john
  • Since, ```name in SQL function: john``` isn't ```name``` set? The problem seems to root on the missing arguements "data" and "hash" in Object.compare – promet99 May 20 '21 at 01:49
  • This seems a very comment misunderstanding. `await` ONLY does anything useful if you are awaiting a promise that is connected to your asynchronous operation. So, the `await` in `await db.query(..., function()[ ... })` does nothing because when you pass a callback, then `db.query()` does NOT return a promise. Either code with promises or plain callbacks, not a mix. And, `return await result[0];` also illustrates that you need to go learn about what `await` actually does as it does nothing at all there. – jfriend00 May 20 '21 at 02:33

3 Answers3

0

When you use db.query with a callback, it does not return a promise

Try the following code instead

const getUserByUsername = async (username, db) => {
    const QUERY = `SELECT * FROM ${table_name} WHERE username = '${username}'`;
   
    const result = await db.query(QUERY);
    console.log("name in SQL function: " + result[0].username);
    return result[0];
};
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
  • Tried this now, the console.logs are now in the right order, but I get "name in SQL function: undefined" now and getUserByUsername() returns undefined. – Herman Bjørnerud May 20 '21 at 02:17
  • @HermanBjørnerud - odd - what does `console.log(result)` look like? and `console.log(result[0])` - if anything, that part of the code is functionally identical to your code, just done correctly for `await` - perhaps you did something wrong? – Jaromanda X May 20 '21 at 04:01
0

Please try the below code.

const getUserByUsername = async (username, db) => {
try {
    const QUERY = `SELECT * FROM ${table_name} WHERE username = '${username}'`;

    const user = await db.query(QUERY, async (err, result) => {
        if (err) {
            throw err;
        }
        if (result && result.length) {
            return result[0];
        }
        throw new Error(`User with username ${username} not found`);
    });

    console.log(`name in SQL function: ${user.username}`);
    return user;

} catch (error) {
    console.log(error);
    throw error; 
}

};
Ashok Kumar
  • 326
  • 2
  • 8
0

After jfriend00's comment, I decided to make my function a callback function. I found this answer explaining how to do it: https://stackoverflow.com/a/31875808/6817961. This worked!

My code now:

    // Function returns a user object
      const getUserByUsername = (username, callback) => {

        const QUERY = `SELECT * FROM ${db_name} WHERE username = '${username}'`;

        db.query(QUERY, (err, result) => {

          if (!err) {

            if (result.length > 0) {
              return callback(null, result[0]);

            } else {
              err = "No user with that username";
              return callback(err, null);
            }

          } else {
            return callback(err, null);
          }
        });
      };

 // Then this function does stuff with the callback
  const authenticateUser = (username, password, done) => {

    getUserByUsername(username, async (err, result) => {

      if (err) {
        console.log(err);
        return done(null, false, { message: err });

      } else {
        const user = result;
        // result will now return the user object!