1

I'm trying to tack on a few extra variables to a list of items called "cities" before it goes back to the client in my new sails.js app. Sails.js uses Underscore.js to do basic functional programming.

here is what I have currently using _.each. (I first tried to use _.map and return User but that didn't work either).

The console correctly logs each individual user, but cities_with_count is empty in the _.each case "[]" and two undefined's in the _.map case "[ undefined undefined ]"

    User.findByIdIn(user_ids).then(function(users){
    var users_with_counts = []
    _.each(users, function(user) {
      Candy.count({ type: "yummy").then(function(candy_count){
        user.candy_count = candy_count
        console.log(user);
        users_with_count.push(user);
      });
    });

    console.log(users_with_count);
    res.view({
      users: users_with_count
    });
  });
ajbraus
  • 2,909
  • 3
  • 31
  • 45

1 Answers1

0

underscore loops through the users synchronously, and then for each user it issues an asynchronous request:

Candy.count({ type: "yummy").then(function(candy_count){
...
});

By the time the _.each loop ends, the requests may not have necessarily all been processed, because there is no way to know when the reply will come from the backend and in which order.

When the code goes on the array users_with_counts is not yet populated, leading to unwanted behavior.

One way of handling these scenarios is to use a counter to see how many count queries where made, and go on with the logic only when all queries are finished. Either do a seInterval and periodically check the value of the counter or add a if condition after filling the array to see if the program can go on.

But if errors occur your program will hang, the best long term option is to use a promises library like for example q.

Angular University
  • 42,341
  • 15
  • 74
  • 81
  • Is there anyway to force these counts to be synchronous? – ajbraus Dec 08 '13 at 23:06
  • No it's actually not possible, it's the whole thing with node almost all the API's from both the core and libraries are synchronous, this is by design. The goal is to never block the event thread because there is only one such thread, and blocking it would block the server. This causes the code to have a lot of callbacks (see callback hell) http://stackoverflow.com/questions/18095107/callback-hell-in-nodejs to deal with having asynchronous calls everywhere. An alternative are promises libraries like q, hope it helps. – Angular University Dec 08 '13 at 23:15