Trong Lam Phan Trong Lam Phan - 4 months ago 11
Node.js Question

Use value in mongoose scope function

I'd like to find mails of a user by his id. But i have a problem because mongoose function is async.

Mail.find({receiver_id: '#id#'}, function(err, mails) {
var result = [];
var count = 0;
if (mails.length > 0) {
for (m of mails) {
User.findById(m.sender_id, function(err, user) {
if (user) {
result.push({
id: m._id,
title: m.title,
body: m.body
});
if (++count == mails.length) {
res.json({success: true, data: result});
}
}
});
}
} else {
res.json({success: false, error: 'Cannot find any email'});
}
});


The problem is, when i got my result, all mails were the same. As i understood, because User.findById is an async function, so when i use m in that function, the m always represents the last child of mails.

I've figured out that if i pass some variables as the second param of findById function, it should work:

User.findById(m.sender_id, {id: m._id, title: m.title, body: m.body}, function(err, user) {
if (user) {
result.push({id, title, body});
if (++count == mails.length) {
res.json({success: true, data: result});
}
}
});


but because my document doesn't have only three fields, so i think there's another better solution.

How can i get it right ? Thanks !

Answer
var async = require("async");
var yourResult = [];
async.each(mails, function(mailObj, done){
   User.findById(mailObj.sender_id, function(err, user) {
       //add data into result. call async callback function.
       done();
   })
}, function(err){
  //final callback write res here
  result.push(yourResult);
  res.json({success: true, data: result});
});

Async docs here. http://caolan.github.io/async/index.html Hope this helps.