javascript - forEach over array with .push into another array -
this question has answer here:
i'm working on node / mongoose / express app , i'm having problem getting array update while using foreach. i'm not 100% sure i'm missing. have synchronous vs asynchronous? may have return wrong.
router.route('/:slug/episodes') .get(function(req, res) { var episodearray = []; var episodedetails = null; show.findone({ 'slug': req.params.slug }, function(err, show) { if (err) { res.send(err); } var episodes = show.episodes episodes.foreach(function(episodeid, index) { episode.findbyid(episodeid, function(err, episode) { if (err) { res.send(err); } episodearray.push(episode); }); }); res.send(episodearray) }); });
episodearray isn't getting episode added in , ends being full of null values.
your code suffering misunderstanding of how async works. first , foremost should read felix kling link @elclanrs posted here. contributors tend tired of answering same async question on , over. haven't quite gotten tired yet, i'll bite purposes of explaining async, i'll suggest option might better way solve problem.
the async solution: there many ways await array of asynchronous operations complete. async.queue
popular choice. how works push set of pending operations queue , tell queue wait until results have been received, @ point perform res.send(). code this:
var async = require('async'); show.findone({ 'slug': req.params.slug }, function(err, show) { if (err) { res.send(err); } var episodearray = []; var queue = async.queue(function(episodeid, callback) { episode.findbyid(episodeid, function(err, episode) { if (err) { throw err; } episodearray.push(episode); callback(); }); }); // note foreach synchronous. // tasks pushed queue before drain() episodes.foreach(function(episodeid, index) { queue.push(episodeid); }); queue.drain = function() { res.send(episodearray); }; });
this not best way solve problem, purpose of demonstrating how fix existing code.
as long episodes array not obscenely huge, far better way query episodes might use mongodb's $in
operator, so:
show.findone({ 'slug': req.params.slug }, function(err, show) { if (err) { res.send(err); } episode.find({ _id: { $in: show.episodes } }, function(err, episodes) { if (err) { throw err; } res.send(episodes); }); });
edit:
if want go bit deeper, should mention mongoose supports promises, can use make code less nested , repetitive, this:
show.findone({ slug: req.params.slug }) .then(function(show) { return episode.find({ _id: { $in: show.episodes } }); }) .then(function(episodes) { res.send(episodes); }) // errors returned above short circuit middleware next() here .error(next);
Comments
Post a Comment