2011-05-30 132 views
53

一切我可以找到一个撕心裂肺页面猫鼬结果说做这样的:如何从find方法返回Mongoose结果?

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

我怎么能返回结果从查询,更喜欢这个?

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

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

喜欢:

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

res.render('profile/profile', { 
     users: a_users 
    , articles: a_articles 
}); 

可以这样做?

+1

当[ES7滚动](http://jakearchibald.com/2014/es7-async-functions/)时,你的梦想就会实现。 – royhowie 2015-06-13 04:23:15

+1

你应该签出[deasync](https://www.npmjs.com/package/deasync),所以函数看起来像是同步执行的。 – 2015-07-25 21:24:01

+0

为更好地理解这个问题和它的解决方案参考https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – devprashant 2017-06-02 16:49:10

回答

66

你试图强制一个同步范例。只是没有工作。 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 
}); 
+0

@josh有没有办法在第二个函数中访问第一个函数的结果?或者它们只在回调中可用? – pkyeck 2011-07-14 14:03:31

+4

@pkyeck你可以使用瀑布或其他连续做事情的方法。在这个例子中,这两个方法都允许使用process.nextTick并行运行,这意味着函数1的结果不可用于函数2 – Josh 2011-07-19 16:47:19

+0

异步NPM似乎非常强大,有时我们需要一些同步任务。 – Ito 2013-02-19 21:54:20

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 
    }); 
    }); 
}); 

几乎每一个功能是在Node.js的异步猫鼬的发现也是如此。如果你想连续调用它,你应该使用类似Slide库。

但在你的情况,我认为最简单的方法是嵌套回调(这允许f.e. quering文章为选定的以前的用户)或完全平行异步库的帮助(见Flow control/Async goodies)。

+0

我想我可以做这样,但是没有解决我的更重要的问题。我的例子可能不是最好的。我了解保持异步,但最大的问题是我试图将代码更加组织成更真实的MVC时尚,并且很难做到这一点。我讨厌在每个页面的控制器中我必须做出所有这些查询的想法 - 在我的脑海中应该在模型中处理。 所以我想弄清楚保持模型在一个地方,请求信息并将其返回给控制器的方法。 – MrBojangles 2011-05-31 02:50:30

+0

@ user776796在我的项目中,我将模型放置在控制器之前加载的单独文件中。 Mongoose的模型在我的模型中,我为经常使用的查询添加了快捷函数。 – 2011-05-31 08:42:21

+0

这听起来像我如何设置的东西。你如何从快捷功能返回查询结果? – MrBojangles 2011-05-31 14:25:06

1

我有,我用相当多的当了一回节点功能的功能。

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

然后我在所有签名中都有一个可选的回调参数。

1

我正在处理一个非常类似的事情,但使用来自客户端的socket.io和数据库访问。我的发现是在数据库有机会获取数据之前将我的数据库的内容返回给客户端...所以为了什么值得我在这里分享我的发现:

我的检索数据库的函数:

//读取主板 - 完整的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()); 
    }; 

我的插座事件侦听器:

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); 
     }); 
    }); 

所以要解决我们使用猫鼬给我们的承诺的问题然后一旦我们从DB我的插座发出它返回给客户端...

为了什么它的价值...

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! 
    }); 

主要部分如下:

Promise.promisifyAll(mongoose); 

使所有的猫鼬(和它的型号)可作为返回的承诺函数的方法,用Async后缀(.exec()变为.execAsync(),依此类推)。 .promisifyAll()方法在Node.JS世界中几乎是通用的 - 您可以在提供异步函数的任何东西上使用它,以回调作为其最后一个参数。

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

.props()蓝鸟方法需要在目标与承诺作为其属性,并返回集体承诺当两个数据库查询(在这里 - 承诺),其得到解决返回结果。解决的价值是我们的最终功能results对象:

  • results.users - 用户在数据库中发现猫鼬
  • results.articles - 通过猫鼬在数据库中找到的文章(D'嗯)

由于你可以看到,我们甚至没有接近缩进回调地狱。两个数据库查询都是并行执行的 - 不需要其中一个等待另一个。代码简短易读 - 实际上在问题本身中发布的希望“非工作示例”的长度和复杂性(或者说缺乏)相当。

承诺是很酷的。使用它们。