0

I'm working with these two functions:

const createProducts = async () => {
  const manufacturers = await getManufactuters()
  console.log(manufacturers)
}

const getManufactuters = () => {
  sql.query('SELECT * FROM Manufacturer', (error, results) => {
    if (error) console.log(error)
    return results
})

createProducts()

When executing the code above my return is undefined. As I'm using await shouldn't the createProducts function wait for getManufactuters to return to execute the console.log?

obs: I'm using the following npm package: https://www.npmjs.com/package/mysql

Tom Lima
  • 1,027
  • 1
  • 8
  • 25
  • 1
    That's not how async JavaScript works. Your `getManufactuters` function, for one thing, returns no explicit value (hence the implicit undefined result you see). Which Node.js SQL package is this? Also worth reading [this](https://stackoverflow.com/questions/6847697/how-to-return-value-from-an-asynchronous-callback-function). – jarmod Oct 05 '21 at 16:31
  • I just edited the question with the package used. In this case, how could I wait for the results of the function below to proceed with the script processing? @jarmod – Tom Lima Oct 05 '21 at 16:33
  • I tried to put a console.log(results) in place of the return results and everything prints correctly. – Tom Lima Oct 05 '21 at 16:36
  • Yes, but that happens later, asynchronously. Your `getManufactuters` function implicitly returns undefined way before the SQL callback happens. Worth reading [this](https://codeburst.io/node-js-mysql-and-async-await-6fb25b01b628) and [this](https://devdotcode.com/interact-with-mysql-database-using-async-await-promises-in-node-js/). – jarmod Oct 05 '21 at 16:37
  • 1
    you have a few issues here...and the answer below to promisify the return is the right one to use. you'll note that there is an implied double-return that the promisify does...your code now returns the data from the callback, to getManufacturers, which doesn't return anything. And the await needs promises...so use the answer. :) – G-Force Oct 05 '21 at 16:40

1 Answers1

2

Well no, as you're not creating a "Promise" within your function "getManufactuters" (*manufacturers ^^). In fact, your method "getManufactuters" is not async and is just using a callback... To get what you want, rewrite the function to this:

const getManufactuters = () => {
  return new Promise((resolve, reject) => {
    sql.query("SELECT * FROM Manufacturer", (error, results) => {
      if (error) {
        reject(error)
        return
      }
      resolve(results);
    });
  });  
};

Refactored to this, it will be a "Promise" now which can be awaited!

try {
  const manufacturers = await getManufactuters(); // will work now
} catch (e) {
  console.log(e);
}

// and this is basically the same...
getManufactuters().then(result => console.log(result)).catch(error => console.log(error))

You need to know that Promise was there first - that was the original way to call something "asynchronous" in javascript and we ended up with all these callbacks "then.then.then" (also known as callback-hell)

Nowadays we have the two very nice keywords "async" and "await". But the basics haven't changed - you can only await a "Promise". But if something doesn't return a Promise, you won't get an error either - funny right? Javascript just "resolves" it immediately, leaving you alone with no result as you experienced in your example.

So, you cannot throw an "await" to just anything which is not returning a Promise. But cool thing is - you can rewrite anything to be a Promise like shown here ;-)

IF something is already implemented completely with "async/await", then it would work... But then the "sql.query" Function should already be implemented in that way (which is not the case). You can always smell that whenever a function is taking a "callback" parameter -> then it's not a Promise ;-)

jebbie
  • 1,418
  • 3
  • 17
  • 27