asynchronously querying the db using mongojs within a for loop

I came across this scenario, where I had to query the db for each item in a collection. I had to spend some time to figure out how to do this. So, I’m posting my solution here.

Since, db querying is asynchronous in nodejs, apiece of code like this would fail.


    for(i=0; i<arr.length; i++) {
        var result = db.collection.find({_id:'some_id'});
        res.write(i+':'+JSON.stringify(result)+',');
    }
    res.end();

The result would simply return undefined here since this db.collection.find() is an asynchronous call.

So, to avoid this,


    for(i=0; i<arr.length; i++) {
        db.collection.find({_id:arr[i].id}, function(err, result) {
        if(!err && result.length>0){
            res.write(arr[i]+':'+JSON.stringify(result[0])+',');
        }
        });
    }
    res.end();

This will definitely solve the async call issue. But, inside res.write(), I am trying to write arr[i]. From the point the db.collection.find() call has been made to the point the result has been returned by the call, the 'i' value would have changed. So,


    arr.foreach(obj) {
        db.collection.find({_id:obj.id}, function(err, result) {
            if(!err && result.length>0){
                res.write(obj+':'+JSON.stringify(result[0])+',');
            }
        });
    }
    res.end();

There is another issue here. Immediately after the foreach loop is executed, there is a res.end() statement. At this point, If there are any pending async calls to the db, the res.write() will fail after res.end() is executed. So, I tweaked the code further more.


    var count=0;
    arr.foreach(obj) {
        db.collection.find({_id:obj.id}, function(err, result) {
            if(!err && result.length>0){
                res.write(obj+':'+JSON.stringify(result[0])+',');
            }
            count++;
            if(count == arr.length){
                res.end()
            }
        });
    }
  1. dominikgar reblogged this from nodeblog
  2. nodeblog posted this