node.js 如何从 find 方法返回 Mongoose 结果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6180896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to return Mongoose results from the find method?
提问by MrBojangles
Everything I can find for rending a page with mongoose results says to do it like this:
我可以找到用猫鼬结果来渲染页面的所有内容都说要这样做:
users.find({}, function(err, docs){
res.render('profile/profile', {
users: docs
});
});
How could I return the results from the query, more like this?
我怎么能从查询中返回结果,更像这样?
var a_users = users.find({}); //non-working example
So that I could get multiple results to publish on the page?
这样我就可以在页面上发布多个结果?
like:
喜欢:
/* non working example */
var a_users = users.find({});
var a_articles = articles.find({});
res.render('profile/profile', {
users: a_users
, articles: a_articles
});
Can this be done?
这能做到吗?
回答by Josh
You're trying to force a synchronous paradigm. Just does't work. node.js is single threaded, for the most part -- when io is done, the execution context is yielded. Signaling is managed with a callback. What this means is that you either have nested callbacks, named functions, or a flow control library to make things nicer looking.
您正在尝试强制使用同步范式。只是不起作用。node.js 是单线程的,在大多数情况下——当 io 完成时,执行上下文被产生。信令通过回调进行管理。这意味着您可以使用嵌套回调、命名函数或流控制库来使事情看起来更漂亮。
https://github.com/caolan/async#parallel
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
});
回答by bardzusny
I'll play the necromancer here, as I still see another, better way to do it.
我将在这里扮演死灵法师,因为我仍然看到了另一种更好的方法。
Using wonderful promise library Bluebirdand its promisifyAll()method:
使用美妙的承诺库Bluebird及其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!
});
Key parts are as follows:
关键部分如下:
Promise.promisifyAll(mongoose);
Makes all mongoose (and its models) methods available as functions returning promises, with Asyncsuffix (.exec()becomes .execAsync(), and so on). .promisifyAll()method is nearly-universal in Node.JS world - you can use it on anything providing asynchronous functions taking in callback as their last argument.
使所有猫鼬(及其模型)方法可作为返回承诺的函数使用,Async后缀为(.exec()变成.execAsync(),依此类推)。.promisifyAll()方法在 Node.JS 世界中几乎是通用的——你可以在任何提供异步函数的东西上使用它,将回调作为它们的最后一个参数。
Promise.props({
users: users.find().execAsync(),
articles: articles.find().execAsync()
})
.props()bluebird method takes in object with promises as its properties, and returns collective promise that gets resolved when both database queries (here - promises) return their results. Resolved value is our resultsobject in the final function:
.props()bluebird 方法接受带有承诺的对象作为其属性,并返回集体承诺,当两个数据库查询(此处 - 承诺)返回其结果时,该承诺得到解决。解析值是我们results在最终函数中的对象:
results.users- users found in the database by mongooseresults.articles- articles found in the database by mongoose (d'uh)
results.users- mongoose 在数据库中找到的用户results.articles- mongoose 在数据库中找到的文章 (d'uh)
As you can see, we are not even getting near to the indentation callback hell. Both database queries are executed in parallel - no need for one of them to wait for the other. Code is short and readable - practically corresponding in length and complexity (or rather lack of it) to wishful "non-working example" posted in the question itself.
如您所见,我们甚至还没有接近缩进回调地狱。两个数据库查询都是并行执行的——其中一个不需要等待另一个。代码简短且可读 - 实际上在长度和复杂性(或者更确切地说是缺乏)与问题本身中发布的一厢情愿的“非工作示例”相对应。
Promises are cool. Use them.
承诺很酷。使用它们。
回答by Oleg Shparber
The easy way:
简单的方法:
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
});
});
});
Practically every function is asynchronous in Node.js. So is Mongoose's find. And if you want to call it serially you should use something like Slidelibrary.
实际上,Node.js 中的每个函数都是异步的。Mongoose 的发现也是如此。如果你想连续调用它,你应该使用类似幻灯片库的东西。
But in your case I think the easiest way is to nest callbacks (this allows f.e. quering articles for selected previously users) or do it completly parallel with help of async libraries (see Flow control / Async goodies).
但在你的情况下,我认为最简单的方法是嵌套回调(这允许为选定的以前的用户查询文章)或在异步库的帮助下完全并行(参见Flow control / Async goodies)。
回答by Joe
I have a function that I use quite a bit as a return to Node functions.
我有一个函数,我经常使用它作为对 Node 函数的返回。
function freturn (value, callback){
if(callback){
return callback(value);
}
return value;
};
Then I have an optional callback parameter in all of the signatures.
然后我在所有签名中都有一个可选的回调参数。
回答by Sten Muchow
I was dealing with a very similar thing but using socket.io and DB access from a client. My find was throwing the contents of my DB back to the client before the database had a chance to get the data... So for what it's worth I will share my findings here:
我正在处理一个非常相似的事情,但是从客户端使用 socket.io 和 DB 访问。我的发现是在数据库有机会获取数据之前将我的数据库的内容扔回客户端......所以我将在这里分享我的发现:
My function for retrieving the DB:
我检索数据库的功能:
//Read Boards - complete DB
//读板 - 完整的数据库
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());
};
My socket event listener:
我的套接字事件侦听器:
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);
});
});
So to solve the problem we use the promise that mongoose gives us and then once we have received the data from the DB my socket emits it back to the client...
所以为了解决这个问题,我们使用猫鼬给我们的承诺,然后一旦我们从数据库接收到数据,我的套接字就会将它发送回客户端......
For what its worth...
物有所值...
回答by Surender Singh
You achieve the desired result by the following code. Hope this will help you.
您可以通过以下代码获得所需的结果。希望这会帮助你。
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);
});

