0

I'm using node-mysql to execute a query and return results. Per standard mysql-node documentation, a callback function is executed once the query is complete passing an error object or result object. Assuming the query executed correctly (and it does). I run through a for-in loop on the result and assign the fields in each row as one continuous message that I plan to send back to the calling so that it can be processed appropriately. So, if a user wants to see the last 5 picks from a fantasy football draft, the function receives the num parameter (which is equal to 5) and then see a returned message showing details about all 5 picks transactions. The function is as follows:

exports.getSelections = function(num){


 var query = "Select b.Player, b.Team, b.Position, a.Pick, c.Owner FROM Players b, Owners c,(Select * FROM Draft2 WHERE Year=2015 AND Player_ID >0 ORDER BY PICK DESC LIMIT " + num + ") a WHERE b.Player_ID = a.Player_ID AND c.Owner_ID = a.Owner_ID ORDER BY a.Pick DESC";


 var connection = mysql.createConnection(EXTERNAL_DATABASE_URL);
 connection.query(query, function(err, results, fields){
                    if(!err){
                        for( var i in results){
                            msg += "\n" + results[i].Pick + ". " + results[i].Owner + " selected " + results[i].Player + ",  " + results[i].Position + " from " + results[i].Team 
                        }

                    }else{
                        console.log(err);
                            msg = "There was an error processing your request";
                    }
                });      


                    connection.end(function(err){
                        if(err){
                            console.log("there was an error")
                        }else{
                            console.log("close connection");
                        }
                    });




                        console.log("message to be sent: " + msg);
                        return msg;         

};

The output through my console is always:

message to be sent: undefined

this is what processed: [shows the details of the sales transactions based on the number that was passed to the function and used in the query]

I see the results of the query in the second line above, as represented by [msg], so I know the query executed appropriately.

Here are my questions:

  1. Can I get an explanation why the console would execute the message to be sent before finishing the actual loop.

  2. If I want to ensure that the loop is complete before returning the value, how do I approach this?

  3. Also, it appears that connection.end doesn't execute either. I presume I'm exiting the function too early??

Thanks for any help.

boody
  • 17
  • 8
  • 1
    What "loop" are you talking about? There's no loop in the code you posted. Database operations are **asynchronous**; that's why you pass callbacks to deal with the results. – Pointy Oct 26 '15 at 02:22
  • 1
    Can you please post your complete code? There seem to be some indentation and probably scoping problems. – Bergi Oct 26 '15 at 02:26
  • The loop that I'm referring to is the for(var i in results). – boody Oct 26 '15 at 02:41
  • With the given code, if your query completes successfully but with an empty result set, `msg` will be undefined. – keithmo Oct 26 '15 at 03:33
  • it doesn't have any empty result set. The user can request the last 5, 10, etc records in a database table. The num parameter is passed to the function and is used in the query. I see the results when a number is passed but it looks like the code is evaluating the console.log("message to be sent: msg") before completing the for-in loop which is populating the msg variable. – boody Oct 26 '15 at 03:46
  • You are not declaring your `msg` variable anywhere. Also, there is a missing closing `});` somewhere. Can you please fix your syntax error? It's important for us to know where the `connection.query(…` callback ends. – Bergi Oct 26 '15 at 09:35
  • The "msg" variable is global - defined outside the scope of the function. When I initiate the server, i declare it as a variable. I've also copied the complete function. My apologies for the confusion. – boody Oct 26 '15 at 21:21

1 Answers1

0

As @Pointy hinted, the log is executing prior to the completion of the loop because the database operation connection.query is asynchronous. All of your operations are being executed in the correct sequence; its just that async operations resolve on their own timeline, which is why we have callbacks that run upon their completion.

You've already logged the value of msg before your connection.query callback even gets a chance to run.

Try moving your "message to be sent" console.log inside of the callback of the connection.query operation:

exports.getSelections = function(num) {
  var query = "Select b.Player, b.Team, b.Position, a.Pick, c.Owner FROM Players b, Owners c,(Select * FROM Draft2 WHERE Year=2015 AND Player_ID >0 ORDER BY PICK DESC LIMIT " + num + ") a WHERE b.Player_ID = a.Player_ID AND c.Owner_ID = a.Owner_ID ORDER BY a.Pick DESC";
  var connection = mysql.createConnection(EXTERNAL_DATABASE_URL);
  connection.query(query, function(err, results, fields) {
    if (!err) {
      for (var i in results) {
        msg += "\n" + results[i].Pick + ". " + results[i].Owner + " selected " + results[i].Player + ", " + results[i].Position + " from " + results[i].Team
      }
    } else {
      console.log(err);
      msg = "There was an error processing your request";
    }

    console.log("message to be sent: " + msg);

  });
  connection.end(function(err) {
    if (err) {
      console.log("there was an error")
    } else {
      console.log("close connection");
    }
  });

  return msg;
};

Also, might want to make sure msg is of type String before concatenating with msg += "..."

SteamDev
  • 4,294
  • 5
  • 20
  • 29
  • I did try that but wasn't having much luck. I did get it to work shortly after posting my updates to the code but I had to do it by creating a callback within the calling function and passing that as part of the parameters of the main function. Should I be able to return the msg variable from within the main function I'm showing above? – boody Oct 26 '15 at 22:44