Il ciclo forEach nel tuo tentativo non riconosce il completamento della callback di findById()
metodo asincrono prima dell'iterazione successiva. Devi utilizzare uno qualsiasi dei async
metodi della libreria async.each
, async.whilst
o async.until
che sono equivalenti a un ciclo for e attenderanno finché non viene richiamata la richiamata di async prima di passare all'iterazione successiva (in altre parole, un ciclo for che produrrà).
Ad esempio:
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);
});
Per l'intera operazione, puoi utilizzare async.waterfall()
metodo che consente a ciascuna funzione di passare i propri risultati alla funzione successiva.
La prima funzione nel metodo crea il nuovo articolo.
La seconda funzione usa async.each()
funzione di utilità per scorrere l'elenco delle piattaforme, eseguire un'attività asincrona per ciascun ID per aggiornare la piattaforma utilizzando findByIdAndUpdate()
, e al termine restituiscono i risultati della query di aggiornamento in una variabile oggetto alla funzione successiva.
La funzione finale aggiornerà l'articolo appena creato con gli ID piattaforma della pipeline precedente.
Qualcosa come il seguente esempio:
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);
});