1

I cannot find a way to get my find function to work. I would like to find all billIds from the bills collection and then check for each billId inside the transaction DB.

The problem is, because of the aSynch - I reckon, the id doesn't update on my loop. Here is the code:

Bills.find({type: bill_type, endDate: {"$gte" : new Date(year + "-" + month + "-1")}}).find(function(err, bills){
        if(err)
            res.send(err);

        details.bills = bills;

        for(key in bills){
            var billId = bills[key]._id;
            console.log("BillId: " + billId); // Here the ids are unique (which is what I want)

             Transactions.find({billId : billId}, function(err, transactions){
                if (err) {
                    console.log('error: '+ err)
                } else {
                    console.log("Transaction BillId: " + billId); // Here I get always the same ID - which is not quiet what I need.
                }
            });


            //console.log(transactions);
        }

       res.send(details);  
    });

There result at the console is:

BillId: 549bf0597886c3763e000001
BillId: 54a014bfac01ca3526000001
BillId: 54a015753547a6c026000001

^ Good result - Comes from the first console.log inside the for().

and then:

Transaction BillId: 54a015753547a6c026000001
Transaction BillId: 54a015753547a6c026000001
Transaction BillId: 54a015753547a6c026000001

^ Bad result - Its repeating the last result from the for() and I need all results.

At the first console.log(), when I get the results from the first find() (Bills.find()), I can see all the ids on the log but when I try to get them inside the second Find (Transactions.find()), they repeat the last id. So in this current state I am not able to query the db for each id. Any help on this is appreciated.

Please let me know if you need any clarification.

Thanks in advance!

Deisy Laymi
  • 343
  • 1
  • 2
  • 10
  • `var billId = bills[item]._id;` should be `var billId = item._id`. – BatScream Jan 03 '15 at 12:14
  • Thats not the point. I'm getting the billId there, the problem is that when I try to execute a `Transactions.Find()` on each billId, the billId is always the last billId from the `Bills.find()`. Also, your suggestion will not work since the item represent the key in my array. – Deisy Laymi Jan 03 '15 at 12:19

3 Answers3

0

If your Transactions.find function is asynchronous, its callback runs at a later point in time, long after the for ... in cycle is finished. At that time, billId has the value it was assigned on the last run of the for ... in cycle. Therefore, all runs of the callback print out that value.

If you want to hold on to the value, you'll have to create a closure somewhere, like this:

(function (id) {
    Transactions.find(..., function (...) {
        // ... use `id` here
    });
})(billId);

If bills is an Array or if you're using some utility library like Lo-Dash, you could use iteration function like Array.prototype.map or lodash.each that uses a closure, so that you wouldn't have to create one separately.

hon2a
  • 7,006
  • 5
  • 41
  • 55
0

Classic mistake of closure function inside the loop.

Your variable value change every loop step. Your function on the other hand will be executed later ( after some time ) when the variable already changed many times.

Take a look on the links for clarification:

Creating closures in loops: A common mistake

JavaScript closure inside loops – simple practical example

Javascript infamous Loop issue?

Community
  • 1
  • 1
Thiago Felix
  • 166
  • 3
0

Perfect!

Thanks for the tips guys. I resolved it using Underscore each function.

Here is how: Instead of looping with for, I simple replaced the for by _.each as in the below example:

Bills.find({type: bill_type, endDate: {"$gte" : new Date(year + "-" + month + "-1")}}).find(function(err, bills){
    if(err)
        res.send(err);

    details.bills = bills;

    _.each(bills, function(item){        
        var billId = item._id; 
        console.log("BillId: " + billId); 

         Transactions.find({billId : billId}, function(err, transactions){
            if (err) {
                console.log('error: '+ err)
            } else {
                console.log("Transaction BillId: " + billId);
            }
        });


        //console.log(transactions);
    });

   res.send(details);  
});
Deisy Laymi
  • 343
  • 1
  • 2
  • 10
  • If an answer solved your problem, it's better to mark it as _accepted_ than to repost the whole code with a tiny change in a separate answer. – hon2a Jan 04 '15 at 09:03
  • Thanks! But I actually like to post exactly what solve the problem as I believe not everyone here are experts like you guys and a suggestion doesn't always clarify what exactly you need to do to get your problem solved. So posting the right-to-the-dot solution will help other amateurs like me. – Deisy Laymi Jan 04 '15 at 09:08