2

I am attempting to pass the data variable from the function to the app.get call. But the global variable 'data' in my function is not retaining the value returned from the database query. I believe this to be a scoping issue. I set the value for 'data' to null at the beginning to make the variable accessible throughout the function. I am not hitting either of the error conditions.

function getCommands(query) {
    var data = null;
    try {

    pg.connect(cString, function(err, client, done) {
        // Catch any connection errors, and display them to the screen
        if(err) {
            return console.error('could not connect to postgres', err);
        }

        client.query(query, function(q_err, result) {

        // Release the client back to the pool
        done();

        if(q_err) {
            return console.error('error running query', q_err);
        }

        // Data object with an empty array to hold the row information
        data = {"data":[]};

        for (var row in result.rows)
        {
            //console.log(result.rows[row]);
            data.data.push(result.rows[row]);
        }
        //Here, data, has the correct return values.
        console.log(data);
        });

    });

    }
    catch( e )
    {
        console.log(e);
    }
    //Here, data, is null.
    console.log(data);
    return data;

}

app.get('/clients/', function(req, res) {
    res.send(getCommands('SELECT clientid, clientname FROM hourglass.clients ORDER BY clientid ASC'));
});

Could someone help me determine why 'data' is not retaining value outside of the pg.connect function?

Craig Ringer
  • 307,061
  • 76
  • 688
  • 778
Ben Pingilley
  • 729
  • 1
  • 6
  • 13
  • possible duplicate of [Variable doesn't get returned from AJAX function](http://stackoverflow.com/questions/12475269/variable-doesnt-get-returned-from-ajax-function) – Denys Séguret Feb 04 '14 at 16:02
  • 1
    It doesn't "retain" that value because you log the value **before** the callback is called. You can't return a value from a function computing that value asynchronously. – Denys Séguret Feb 04 '14 at 16:02
  • 1
    I'd recommend you to look into promises to solve that problem. Here's an article I wrote on how to use them for postgres accesses : http://canop.org/blog/?p=516 – Denys Séguret Feb 04 '14 at 16:05
  • Thank you for pointing out the asynchronous problem within the code. Due to the simplicity of this code, I went the route of doing a callback function rather than implementing promises. This code is now working as planned. Because of my 'newbieness' to the website, I am unable to post my new code as an answer just yet. But I will post it after the 8 hours of first posting my question has passed. Thanks again for the help! – Ben Pingilley Feb 04 '14 at 16:39
  • You're welcome. Glad to see you understood. – Denys Séguret Feb 04 '14 at 16:41
  • @dystroy The first comment with the possible duplicate was the exact methodology I needed. Thanks. – Ben Pingilley Feb 04 '14 at 16:42

2 Answers2

2

I think your problem is not that the variable is not retaining the value outside of the function, but rather that you console.log(data) is executing before the variable is set.

If you were to put console.log('step X') in your code as in the following example you'll see the sequence in which your code is executed.

function getCommands(query) {
    var data = null;
    console.log('STEP 1');

    pg.connect(cString, function(err, client, done) {

        console.log('STEP 3');

    });

    console.log('STEP 2');

}
Hector Correa
  • 26,290
  • 8
  • 57
  • 73
  • Yeah, I am not trying for fix his code, but rather show him the execution of the steps via the the console.log('STEP X') lines. – Hector Correa Feb 04 '14 at 16:06
1
function getCommands(query, callback) {

try {

    pg.connect(cString, function(err, client, done) {
        // Catch any connection errors, and display them to the screen
        if(err) {
            return console.error('could not connect to postgres', err);
        }

        client.query(query, function(q_err, result) {

            // Release the client back to the pool
            done();

            if(q_err) {
                return console.error('error running query', q_err);
            }

            // Data object with an empty array to hold the row information
            var data = {"data":[]};

            for (var row in result.rows)
            {
                data.data.push(result.rows[row]);
            }
            callback(data); //After data is set, the value is passed back
        });
    });
}
catch( e )
{
    console.log(e);
}
}

app.get('/clients', function(req, res) {.....])

Using a callback function mentioned by @dystroy worked perfectly.

Ben Pingilley
  • 729
  • 1
  • 6
  • 13