如何从find方法返回Mongoose结果?

MrB*_*les 55 mongoose mongodb node.js express

我找到的用于渲染具有猫鼬结果的页面的所有内容都说是这样做的:

users.find({}, function(err, docs){
    res.render('profile/profile', {
        users:     docs
    });
});
Run Code Online (Sandbox Code Playgroud)

我怎么能从查询中返回结果,更像这样?

var a_users = users.find({}); //non-working example
Run Code Online (Sandbox Code Playgroud)

这样我就可以在页面上发布多个结果?

喜欢:

/* non working example */
var a_users    = users.find({});
var a_articles = articles.find({});

res.render('profile/profile', {
      users:    a_users
    , articles: a_articles
});
Run Code Online (Sandbox Code Playgroud)

可以这样做吗?

Jos*_*osh 67

你试图强制实施同步范式.只是不工作.node.js是单线程的,大多数情况下 - 当完成io时,会产生执行上下文.通过回调来管理信令.这意味着您要么具有嵌套回调,命名函数,要么使用流控制库来使事情更好看.

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
});
Run Code Online (Sandbox Code Playgroud)

  • @pkyeck你可以使用瀑布或其他一些连续执行的方法.在此示例中,允许这两种方法使用process.nextTick并行运行,这意味着函数1的结果不可用于函数2 (4认同)
  • 这是有效的,是非常好的答案(upvoted it!:)),但这些天 - 我会说使用`async`进行并行任务有点过时了.考虑到这个解决方案是在2011年编写的,这是完全可以理解的.**Promises**在处理异步任务时提供了更大的灵活性,我建议任何人在使用不同的解决方案之前考虑使用它们(**免责声明:**I在这个帖子中发布了答案,证明了他们在这种情况下的使用). (3认同)

bar*_*sny 20

我会在这里扮演死灵法师,因为我仍然会看到另一种更好的方法.

使用精彩的诺言库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!
  });
Run Code Online (Sandbox Code Playgroud)

关键部分如下:

Promise.promisifyAll(mongoose);
Run Code Online (Sandbox Code Playgroud)

使所有mongoose(及其模型)方法可用作返回promise的函数,带Async后缀(.exec()变为.execAsync()等等)..promisifyAll()方法在Node.JS世界中几乎是通用的 - 你可以在提供异步函数的任何东西上使用它,将回调作为它们的最后一个参数.

Promise.props({
    users: users.find().execAsync(),
    articles: articles.find().execAsync()
  })
Run Code Online (Sandbox Code Playgroud)

.props()bluebird方法接受带有promises作为其属性的对象,并返回在两个数据库查询(此处为promises)返回结果时得到解决的集合promise.已解析的值是results最终函数中的对象:

  • results.users - 由mongoose在数据库中找到的用户
  • results.articles - mongoose(d'uh)在数据库中找到的文章

正如你所看到的,我们甚至没有接近缩进回调地狱.两个数据库查询都是并行执行的 - 不需要其中一个等待另一个.代码简短且易读 - 在问题本身中发布的如意"非工作示例"实际上与长度和复杂性(或者说缺乏它)相对应.

承诺很酷.使用它们.


Ole*_*ber 16

简单的方法:

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
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

实际上,每个函数在Node.js中都是异步的.Mongoose的发现也是如此.如果你想连续调用它,你应该使用像Slide库这样的东西.

但是,在你的情况,我认为最简单的方法是窝回调(这允许FE quering文章之前选择的用户)或不完全地它与异步库的帮助下平行(见流量控制/异步好吃的东西).

  • @ user776796我没有返回结果但传递给传递给快捷方式功能的回调. (4认同)