2015-05-22 3 views
2

Это пример того, что я пытаюсь сделать, получить все сообщение внутри mongo db, поскольку каждый пост заполняет автора тогда используйте объект author для получения изображения профиля из Cloudinary.Как я могу заполнить массив во время асинхронного вызова и отправить его в объект-ответ.

Каков правильный способ сделать это? Я пробовал множество способов заполнения массивов и отправки их в ответ, но из-за асинхронного вызова они никогда не запускаются до отправки res.

router.get('/posts',auth, function(req, res, next) { 
    //var id = req.payload._id; 
    Post.find(function(err, posts){ 
    if(err){ return next(err); } 
    posts.forEach(function(post){ 
     post.populate('author',function(err,post){ 
     post.image = cloudinary.image("v"+post.author.avatarVersion+"/profile/"+post.author._id,{ 
      width:100, height:100,crop:'thumb',gravity:'face',radius:'max' 
     }) 
     //here the post object is updated 
     console.log(post) 
     }) 
    }) 
    //res.json(some posts array); 
    }); 
}); 

Решение спасибо Dan Moldova!

router.get('/posts',auth, function(req, res, next) { 
    var id = req.payload._id; 

    Post.find({}).populate('author').exec(function(err,posts){ 
    if(err){ return next(err); } 
    var updatedPosts = []; 
    posts.forEach(function(post){ 
     post.image = cloudinary.image("v"+post.author.avatarVersion+"/profile/"+post.author._id,{ 
      width:100, height:100,crop:'thumb',gravity:'face',radius:'max' 
     }) 
     updatedPosts.push(post); 
    }) 
    res.json(updatedPosts); 
    }) 

ответ

1

Вы можете просто ЦЕПЬ populate запроса к первому и иметь окончательный обратный вызов после таких как

Post.find({}).populate('author').exec(function (err, posts) { 
    if(err){ return next(err); } 
    posts.forEach(function(post){ 
     // here each post will already have author appended 
    }); 
}); 
+1

Hey Dan, благодарю вас за ответ! Это работает, чтобы сделать население более эффективным. Однако я все еще не могу разместить обновленный массив записей в res.json(). – Nafis

+0

forEach является синхронным, поэтому вы должны иметь возможность res.json массива успешно сразу после forEach –

+0

Ах, вы были правы! Спасибо .. – Nafis

1

решения Дэы является правильным, но я хочу, чтобы объяснить эту проблему Вы сталкиваетесь. Поскольку post.populate() является вызовом базы данных, это означает, что код является асинхронным. Это означает, что следующий пост в forEach() начнет работать до завершения .populate() с предыдущим сообщением. Это означает, что не все сообщения будут завершены до выполнения res.json(). Раствор (который не нужен в этом случае, но может быть использован текущего кода) является использование async library:

var async = require("async"); 

router.get('/posts',auth, function(req, res, next) { 
    var id = req.payload._id; 

    Post.find(function (err, posts) { 
     if (err) { 
      return next(err); 
     } 

     // This is a forEach that waits until all posts are populated before moving on 
     async.each(posts, function (currentPost, postCallback) { 

      currentPost.populate("author", function (err, post) { 

       if (err) { 
        return postCallback(err); 
       } 
       post.image = cloudinary.image("v" + post.author.avatarVersion + "/profile/" + post.author._id, { 
        width: 100, height: 100, crop: 'thumb', gravity: 'face', radius: 'max' 
       }); 
       // the callback function for the current post 
       postCallback(); 
      }); 
     }, function (error) { 
      // the final callback function once all postCallback()'s have been executed, or an error 

      if (error) { 
       return next(error); 
      } 
      // here, everything is finished 
      res.json(posts); 
     }); 
    }); 
}); 

Опять же, решение Dan является правильным, поэтому не используйте этот код. Просто имейте это в виду, когда вы сталкиваетесь с такими проблемами.

+0

Спасибо! Я уверен, что это пригодится. – Nafis

 Смежные вопросы

  • Нет связанных вопросов^_^