Rachel Dockter
Rachel Dockter

Reputation: 986

function is running before sql query is finished, node js

i have made an event listener for my server which listens for when someone is trying to log on, so i do an sql query and then if the info matches, it logs them on. problem is, its testing if the info matches before it runs the query so it will always return false. here is my code

player.on('checkLogin', function(data)
{   
    var logIn = "";
    connection.query({
    sql: "SELECT * FROM users WHERE username = ?", 
    values: [data.user] },


    function(error, results, fields) 
    {                                               
        if (error) 
        { 
            console.log(error); 
        }

        if(results) 
        {   
            var pass = "";  

            for (i = 0; i < results.length; i++)
            {
                pass = (results[i].password);
            }

            var input = crypto.createHash('md5').update(data.pass).digest("hex");

            if (pass == input)
            {
                logIn = true;
            }                       
        }
    });

    if (logIn == true)
    {
        this.em.emit('login', 
            {
            id: player.playerid 
            });
    }
}.bind(this));

I heard promises will fix this but is there any easy way around this?, thanks in advance

Upvotes: 0

Views: 428

Answers (1)

Nico
Nico

Reputation: 12683

The issue you have is your if(login == true) is outside of the completion handlers of the query.

Move the if(logIn == true) into your completion handler.

player.on('checkLogin', function(data)
{   
    var logIn = "";
    connection.query({
    sql: "SELECT * FROM users WHERE username = ?", 
    values: [data.user] },


    function(error, results, fields) 
    {                                               
        if (error) 
        { 
            console.log(error); 
        }

        if(results) 
        {   
            var pass = "";  

            for (i = 0; i < results.length; i++)
            {
                pass = (results[i].password);
            }

            var input = crypto.createHash('md5').update(data.pass).digest("hex");

            if (pass == input)
            {
                logIn = true; //<-- could just handle it here.
            }
            if (logIn == true) //<-- moved inside completion handler
            {
               //log on
            }                       
        }
    });


}.bind(this));

Now the reason it is being called is your connection.query runs asynchronously which is why the function handler is used. Code outside the completion handler will be run immediately.

EDIT from Additional Changes

Based on your changes your this scope will be changed when moved inside the completion handler function. To get a reference back you will need a reference to the player scope (assuming that is what this is). So that can be handled simply by creating a variable of this as var that = this; at the top of your checklogin function. Something like:

player.on('checkLogin', function(data)
{   
    var that = this; //create a variable to store the scope (this)
    var logIn = "";
    connection.query({
    sql: "SELECT * FROM users WHERE username = ?", 
    values: [data.user] },


    function(error, results, fields) 
    {                                               
        if (error) 
        { 
            console.log(error); 
        }

        if(results) 
        {   
            var pass = "";  

            for (i = 0; i < results.length; i++)
            {
                pass = (results[i].password);
            }

            var input = crypto.createHash('md5').update(data.pass).digest("hex");

            if (pass == input)
            {
                logIn = true; //<-- could just handle it here.
            }
            if (logIn == true) //<-- moved inside completion handler
            {
               //log on
              that.em.emit('login',  //<-- reference `that` not `this`
              {
                 id: player.playerid 
              });
            }                       
        }
    });


}.bind(this));

Upvotes: 1

Related Questions