4

I am executing a for loop , inside that for loop i am executing an postgresql query and populating the result into an array. But i cant predict the execution flow.

my code:

var array =[];
       for(var i = 0 ; i< latitude.length; i++){       
    client.query("SELECT value->>'xxxx' as xxxx_details FROM yyyyy WHERE ST_DWithin(ST_GeogFromText('SRID=4326;POINT ("+latitude[i]+" "+longitude[i]+")'), geography(the_geom), " + radius + ")", function(err, row, fields) {               
                       array.push(row.rows[0]);
       }   
                console.log("bbbbbbbbb=" +array);

What i needed is i want the array to be printed after all the query executed inside the for loop. But now its printing before the array is populated. Help me to solve this. Thanks in advance..

2
  • You're missing at least one closing })! Commented Apr 21, 2014 at 11:35
  • Seems simple enough, keep a counter that you increment in the callback for the SQL, and when that counter reaches latitude length, you're all done. Commented Apr 21, 2014 at 11:50

1 Answer 1

6

The reason is client.query is async with results only available in the callback.

One option is async.js. Good write when to use what here.

From that article, you can execute code for each item in a collection. So, for your example, you can have an array of indexes or foreach to build up an array of sql query statements and then execute some for each query.

If queries was an array of queries, then something like:

async.forEach(queries, function(query, callback) {
    client.query(query, function(err, row, fields){
        array.push(row.rows[0]);
        callback(); // this signals async that you're done with this item
    });
}, function(err) {
    if (err) return next(err);

    // all queries are done here
});

Note there's also forEachLimit for doing n in parallel and forEachSeries which has limit of 1 (sequential).

EDIT:

A better option is async / await which is now available if you use typescript and compile to ES6+ and use node 4+ ( has generators ).

I cover the details in this sane node repo

A snippet from that repo shows awaiting an async call in a loop. It keeps it async and doesn't progress to the next line until it completes. This also has the benefit of try / catch handling as you would expect it.

// await allows us to write linear code.  
// makes it easy to also call async code in a loop
// offers easy error handling with try catch
var quotes: IQuote[];
var tries: number = 0;
while (true) {
    try {
        ++tries;
        // ASYNC/AWAIT
        quotes = await this._store.find<IQuote>({});
        break;
    }
    catch (err) {
        if (tries == 3) { throw err; }
    }
}

return quotes;
Sign up to request clarification or add additional context in comments.

2 Comments

You should not use forEach, but map in here. That array thing should be removed.
It should also be noted that using the parallel async.js methods is the same as using the *Series version of the function since MySQL can only execute one query at a time per connection.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.