ottodeluxe
ottodeluxe

Reputation: 25

node js await does not seem to wait

I am making a request to a mySQL Database and want to work with the returned results. I have the async function

async function doQuery(query) {
  try {
    console.log('0. connection start');
    var connection = MySQL.createConnection({  
      host: "xxxxxxxx",
      user: "yyyyyyyy",
      password: "zzzzzzzz"
    });

    console.log('1. Connection set up. Connecting...');
    var queryResults;
    await connection.connect(function(err) {
      if (err) console.log(err);
      console.log("2. Connected!");
      connection.query(query, function(err, result) {
        if (err) console.log(err);
        queryResults = JSON.parse(JSON.stringify(result));
        console.log("3. " + util.inspect(result, {depth: 4}));
        console.log("3.5 " + util.inspect(queryResults, {depth: 4}));
        connection.end();
      });
    })

    console.log ("results before return:" + JSON.stringify(queryResults));
    return queryResults;
  }
  catch (err){
    console.log("async err: " + err);
  }
}

The function is then called from another function:

function handle async(handlerInput) {
  console.log("ExecuteDBSearchHandler");

  var query = buildQuery(handlerInput);
  try{
    var resultsPromise = doQuery(query)
      .then(results => {
        console.log("4. final results: " + results);
        const count = results.length;
        var speechText = 'Abfrage Erfolgreich, es gab ' + count + " Ergebnisse.";
        return handlerInput.responseBuilder
          .speak(speechText)
          .withSimpleCard('Abfrage Erfolgreich', speechText)
          .withShouldEndSession(false)
          .getResponse();
      })
  }
  catch (err){
    console.log("error:" + err);
  }
}

This code is to be used in a nodejs Alexa skill. When the function runs, I would expect the outputs in the log to be ordered ascending. The output I consistently get is 0, 1, 4, 2, 3, 3.5. The .then part is executed before the actual connection is established and the database queried.

Instead of the .then, I tried a simple await before, making the line

var results = await doQuery(query);

This lead to the exact same result. I am at a loss as to why await is infact not waiting. As a sidenote: While inside the block

connection.query(query, function (err, result) {
  if (err) console.log(err);
  queryResults = JSON.parse(JSON.stringify(result));
  console.log("3. " + util.inspect(result, {depth: 4}));
  console.log("3.5 " + util.inspect(queryResults, {depth: 4}));
  connection.end();
});

queryResults shows results (in the debug log step 3.5). In the line

console.log ("results before return:" + JSON.stringify(queryResults));  

it returns undefined. I tried so many things to get the results to the function scope of doQuery, but I can't seem to achieve that. Does the await fail due to this? And how can I fix it? I have read upwards of a dozen articles and docs about async/await and promises, yet I can't figure this out.

Upvotes: 1

Views: 1376

Answers (1)

Ihor Sakailiuk
Ihor Sakailiuk

Reputation: 6058

You need to wrap your callback function in Promise to make use of await keyword

For example:

async function dbQuery(query) {
    try {
        const connection = MySQL.createConnection({  
            host: "xxxxxxxx",
            user: "yyyyyyyy",
            password: "zzzzzzzz"
        });

        return new Promise(function(resolve, reject) {
            connection.connect(function(err) {
                if (err) reject(err);

                connection.query(query, function (err, result) {
                    if (err) reject(err);
                    connection.end();
                    resolve(JSON.parse(JSON.stringify(result)));
                });
            });
        });
    } catch {
        console.error("async err: " + err);
    }
}

The one can also use util.promisify to wrap callback in promise

Upvotes: 2

Related Questions