_.forEach vs Meteor's cursor.forEach or _.map vs Meteor's cursor.map


#1

_.forEach vs cursor.forEach or _.map vs cursor.map .

Suppose I have this code :

var users = Meteor.users.find();
users.forEach(function(item){
    //process item
}) 

//VS

var users = Meteor.users.find();
_.forEach(users.fetch(), function(item){
    //process item
})

Why I must use Meteor’s cursor.forEach instead of _.forEach ?

What are the advantages and disadvantages of Meteor’s cursor.forEach vs _.forEach ?


#2

cursor.forEach iterates the cursor and is reactive. Therefore if used in reactive contexts like helpers, it will set up the reactive computations and your dependencies will rerun when the result of cursor.find changes.

Underscore foreach will just iterate the result array.


#3

@serkandurusoy You’re correct about the reactive part. But as Meteor.users.find() returns a reactive cursor, the underscore part will also be run again after a change in the cursor.

Or did you mean that cursor.forEach is that smart that it will only rerun on the changed items within the collection, while underscore will rerun the loop for all items, when only a single one changed? That would be awesome.

@agusputra I’m not sure if you’re loosing the reactivenes by applying fetch instantly. But by applying it, you’d certainly make the method run slower, as it’s waiting for the cursor’s response.

I’d normally write something like that as:

var users = Meteor.users.find();

if (!users)
  return [];

// it'll only come here after the subscription is ready, no .fetch required
_.forEach(users, function(item){
    //process item
});

#4

I see the source code, cursor.fetch as well as cursor.map internally calling cursor.forEach.

So, I think all methods more or less will behave the same.

https://github.com/meteor/meteor/blob/devel/packages/minimongo/minimongo.js#L196
https://github.com/meteor/meteor/blob/devel/packages/minimongo/minimongo.js#L213


#5

My bad, that’s right. They both are reactive. But in the underscore case, you need to find().fetch() so that you get an iterable array.

Either one will run for the complete result set.

If you want to do something different when there is something changed or be fine grained in that way, you can use observe() and observeChanges() on collections.