Retourne la valeur de la fonction asynchrone dans Nodejs

J'utilise nodejs pour interroger les données de Mongodb throught Mongoose. Après avoir obtenu les données, je veux faire quelque chose sur ces données avant de répondre au client. Mais je ne peux pas obtenir la valeur de retour. Après avoir regardé Google, j'ai appris que les fonctions Node.js sont une fonction javascript asynchrone (blocage non-E / S). J'essaie cette tâche ( http://www.youtube.com/watch?v=xDW9bK-9pNY ), mais ce n'est pas le cas. Voici mon code. Le myObject est évalué à l'intérieur de la fonction "find ()" et non définie en dehors de la fonction "find ()". Alors, que dois-je faire pour obtenir les données? Merci!

var Person = mongoose.model('Person', PersonSchema); var Product = mongoose.model('Product', ProductSchema); var myObject = new Object(); Person.find().exec(function (err, docs) { for (var i=0;i<docs.length;i++) { Product.find({ user: docs[i]._id},function (err, pers) { myObject[i] = pers; console.log(myObject[i]); //return the value is ok }); console.log(myObject[i]); //return undefined value } console.log(myObject); //return undefined value }); console.log(myObject); //return undefined value app.listen(3000); console.log('Listening on port 3000'); 

La raison pour laquelle vous obtenez des valeurs indéfinies est que la fonction de recherche est asynchrone et peut finir à tout moment. Dans votre cas, il se termine après avoir utilisé console.log() , donc les valeurs sont indéfinies lorsque vous les accédez.

Pour résoudre ce problème, vous ne pouvez utiliser que les valeurs dans le rappel de la fonction de recherche. Il ressemblerait à ceci:

 var Person = mongoose.model('Person', PersonSchema); var Product = mongoose.model('Product', ProductSchema); var myObject = new Object(); function getData(docs, callback) { function loop(i) { Product.find({ user: docs[i]._id}, function (err, pers) { myObject[i] = pers; if (i < docs.length) { loop(i + 1); } else { callback(); } }); }; loop(0); }; Person.find().exec(function(err, docs) { getData(docs, function() { // myObject has been populated at this point }); }); 

Le traitement des données a été déplacé vers une boucle qui attend que l'itération précédente soit terminée. De cette façon, nous pouvons déterminer quand le dernier rappel a déclenché pour déclencher le rappel dans la fonction wrapper.

Gardez à l'esprit que, au moment où les fonctions console.log sont exécutées, la requête n'a pas encore terminé, affichera "indéfini". C'est l'essence même de l'asynchronicité de nodeJS.

Par exemple,

 Person.find().exec(function (err, docs) { for (var i=0;i<docs.length;i++) { Product.find({ user: docs[i]._id},function (err, pers) { myObject[i] = pers; console.log(myObject[i]); //return the value is ok }); console.log(myObject[i]); //return undefined value } console.log(myObject); //return undefined value }); console.log(myObject); // <-- Initially, this value will be undefined. After some miliseconds (Or the duration of the .exec function, myObject will contain the results. 

Si vous voulez attendre jusqu'à ce que la requête soit terminée, vous pouvez utiliser les valeurs, je vous recommanderais de déplacer app.listen(3000); Et console.log('Listening on port 3000'); Dans le rappel final de la fonction.

Je vous recommanderais également de vérifier ce module de noeud. Cela vous aidera à créer des fonctions asynchrones / synchrones plus facilement et vous permettra d'exécuter un rappel lorsque toutes les fonctions asynchrones sont terminées.