Comment retourner les résultats de Mongoose à partir de la méthode find?

Tout ce que je peux trouver pour restituer une page avec des résultats fantastiques dit de le faire comme ceci:

users.find({}, function(err, docs){ res.render('profile/profile', { users: docs }); }); 

Comment pourrais-je retourner les résultats de la requête, plus comme ça?

 var a_users = users.find({}); //non-working example 

Pour que je puisse publier plusieurs résultats sur la page?

comme:

 /* non working example */ var a_users = users.find({}); var a_articles = articles.find({}); res.render('profile/profile', { users: a_users , articles: a_articles }); 

Est-ce que cela peut être fait?

Vous essayez de forcer un paradigme synchrone. Juste ne fonctionne pas. node.js est mono-thread, la plupart du temps – lorsque io est terminé, le contexte d’exécution est généré. La signalisation est gérée avec un rappel. Cela signifie que vous avez soit des callbacks nesteds, des fonctions nommées ou une bibliothèque de contrôle de stream pour rendre les choses plus agréables.

https://github.com/caolan/async#parallel

 async.parallel([ function(cb){ users.find({}, cb); }, function(cb){ articles.find({}, cb); } ], function(results){ // results contains both users and articles }); 

Je jouerai le nécromancien ici, car je vois encore une autre meilleure façon de le faire.

Utilisation de la bibliothèque de promesses merveilleuse Bluebird et de sa méthode promisifyAll() :

 var Promise = require('bluebird'); var mongoose = require('mongoose'); Promise.promisifyAll(mongoose); // key part - promisification var users, articles; // load mongoose models "users" and "articles" here Promise.props({ users: users.find().execAsync(), articles: articles.find().execAsync() }) .then(function(results) { res.render('profile/profile', results); }) .catch(function(err) { res.send(500); // oops - we're even handling errors! }); 

Les parties clés sont les suivantes:

 Promise.promisifyAll(mongoose); 

Rend toutes les méthodes de mongoose (et ses modèles) disponibles en tant que fonctions renvoyant des promesses, avec le suffixe Async ( .exec() devient .execAsync() , etc.). .promisifyAll() méthode .promisifyAll() est presque universelle dans le monde Node.JS – vous pouvez l’utiliser sur tout ce qui fournit des fonctions asynchrones en prenant comme dernier argument le rappel.

 Promise.props({ users: users.find().execAsync(), articles: articles.find().execAsync() }) 

.props() prend en object avec des promesses comme propriétés, et retourne une promesse collective qui est résolue lorsque les deux requêtes de firebase database (ici – promesses) renvoient leurs résultats. La valeur résolue est notre object de results dans la fonction finale:

  • results.users – utilisateurs trouvés dans la firebase database par mongoose
  • results.articles – articles trouvés dans la firebase database par mongoose (d’uh)

Comme vous pouvez le constater, nous ne nous approchons même pas de l’enfer du rappel d’indentation. Les deux requêtes de firebase database sont exécutées en parallèle – aucune d’entre elles n’attend l’autre. Le code est court et lisible – il correspond pratiquement en longueur et en complexité (ou plutôt en son absence) à un “exemple de non-travail” dans la question.

Les promesses sont cool. Utilise les.

Le moyen facile:

 var userModel = mongoose.model('users'); var articleModel = mongoose.model('articles'); userModel.find({}, function (err, db_users) { if(err) {/*error!!!*/} articleModel.find({}, function (err, db_articles) { if(err) {/*error!!!*/} res.render('profile/profile', { users: db_users, articles: db_articles }); }); }); 

Pratiquement toutes les fonctions sont asynchrones dans Node.js. Donc, c’est la trouvaille de Mongoose. Et si vous voulez l’appeler en série, vous devez utiliser quelque chose comme la bibliothèque Slide .

Mais dans votre cas, je pense que la manière la plus simple consiste à imbriquer des callbacks (cela permet de rechercher des articles pour des utilisateurs sélectionnés précédemment) ou de le faire complètement en parallèle avec l’aide de bibliothèques asynchrones (voir Goodies Contrôle de stream / Async ).

J’ai une fonction que j’utilise un peu comme retour aux fonctions Node.

 function freturn (value, callback){ if(callback){ return callback(value); } return value; }; 

J’ai ensuite un paramètre de rappel facultatif dans toutes les signatures.

Je traitais une chose très similaire, mais en utilisant l’access socket.io et DB à partir d’un client. Ma découverte a renvoyé le contenu de ma firebase database au client avant que la firebase database ait eu la chance d’obtenir les données … Donc, pour ce que ça vaut, je partagerai mes découvertes ici:

Ma fonction pour récupérer la firebase database:

// Lire les cartes – complète la firebase database

 var readBoards = function() { var callback = function() { return function(error, data) { if(error) { console.log("Error: " + error); } console.log("Boards from Server (fct): " + data); } }; return boards.find({}, callback()); }; 

Mon écouteur d’événement de socket:

 socket.on('getBoards', function() { var query = dbConnection.readBoards(); var promise = query.exec(); promise.addBack(function (err, boards) { if(err) console.log("Error: " + err); socket.emit('onGetBoards', boards); }); }); 

Donc, pour résoudre le problème, nous utilisons la promesse que mongoose nous donne et une fois que nous avons reçu les données de la firebase database, mon socket les renvoie au client …

Pour quoi sa valeur …

Vous obtenez le résultat souhaité par le code suivant. J’espère que ceci vous aidera.

 var async = require('async'); // custom imports var User = require('../models/user'); var Article = require('../models/article'); var List1Objects = User.find({}); var List2Objects = Article.find({}); var resourcesStack = { usersList: List1Objects.exec.bind(List1Objects), articlesList: List2Objects.exec.bind(List2Objects), }; async.parallel(resourcesStack, function (error, resultSet){ if (error) { res.status(500).send(error); return; } res.render('home', resultSet); });