Subburaj
Subburaj

Reputation: 5192

node.js + for loop + query execution

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..

Upvotes: 4

Views: 4670

Answers (1)

bryanmac
bryanmac

Reputation: 39306

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;

Upvotes: 6

Related Questions