Цикълът forEach във вашия опит не разпознава завършването на обратното извикване на findById()
асинхронен метод преди следващата итерация. Трябва да използвате някой от async
библиотечни методи async.each
, async.whilst
, или async.until
които са еквивалентни на for цикъл и ще изчакат, докато се извика обратното извикване на async, преди да преминете към следващата итерация (с други думи, for цикъл, който ще даде резултат).
Например:
var platform_docs = [];
async.each(platforms, function(id, callback) {
Platform.findById(id, function(err, platform) {
if (platform)
platform_docs.push(platform);
callback(err);
});
}, function(err) {
// code to run on completion or err
console.log(platform_docs);
});
За цялата операция можете да използвате async.waterfall()
метод, който позволява на всяка функция да предаде своите резултати на следващата функция.
Първата функция в метода създава новата статия.
Втората функция използва async.each()
помощна функция за итерация в списъка с платформи, изпълнете асинхронна задача за всеки идентификатор, за да актуализирате платформата, като използвате findByIdAndUpdate()
, и когато всички те са готови, връща резултатите от заявката за актуализиране в променлива на обект на следващата функция.
Последната функция ще актуализира новосъздадената статия с идентификаторите на платформата от предишния конвейер.
Нещо като следния пример:
var newArticle = {},
platforms = req.body.platforms,
date = req.body.date,
split = date.split("/");
newArticle.title = req.body.title;
newArticle.description = req.body.description;
newArticle.date = split[2]+'/'+split[0]+'/'+split[2];
newArticle.link = req.body.link;
newArticle.body = req.body.body;
console.log(platforms);
async.waterfall([
// Create the article
function(callback) {
var article = new Article(newArticle);
article.save(function(err, article){
if (err) return callback(err);
callback(null, article);
});
},
// Query and update the platforms
function(articleData, callback) {
var platform_ids = [];
async.each(platforms, function(id, callback) {
Platform.findByIdAndUpdate(id,
{ "$push": { "articles": articleData._id } },
{ "new": true },
function(err, platform) {
if (platform)
platform_ids.push(platform._id);
callback(err);
}
);
}, function(err) {
// code to run on completion or err
if (err) return callback(err);
console.log(platform_ids);
callback(null, {
"article": articleData,
"platform_ids": platform_ids
});
});
},
// Update the article
function(obj, callback) {
var article = obj.article;
obj.platform_ids.forEach(function(id){ article.platforms.push(id); });
article.save(function(err, article){
if (err) return callback(err);
callback(null, article);
});
}
], function(err, result) {
/*
This function gets called after the above tasks
have called their "task callbacks"
*/
if (err) return next(err);
console.log(result);
res.redirect('articles/' + result._id);
});