If you only need to perform synchronous actions for each document, the solution is fairly simple. (console.warn() is synchronous, so you can use it to verify that all user objects are processed first.)
User.find({}).execFind(function(err, users) {
users.forEach(function(user) {
user.age += 1;
userArray.push(user);
console.warn('x');
});
// then...
console.warn('y');
});
If you need to perform some sort of asynchronous action (perhaps another db query), the solution becomes more complex. I encountered this issue recently and briefly debated using a module such as Step or rolling my own barebones solution. Step provided more functionality than I needed, so I decided that the added overhead was not worth it. Here is my solution:
var count = 0;
A.find({ b : c }, ['d', 'e', 'f']).sort(['d'], -1).execFind(function(err, g) {
g.forEach(function(h) {
h.a = [];
B.find({ b : c }, ['d', 'e', 'f', 'g']).execFind(function(err, z) {
g.v = z;
if (++count == g.length)
res.render('z.jade', { locals : { title : 'Q', j : g } });
});
});
});
Please pardon the obfuscation (I yanked that right from the source of a project that is under-wraps). Essentially, you wait until the final async operation to complete.