2011-05-30 138 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'嗯)

由於你可以看到,我們甚至沒有接近縮進回調地獄。兩個數據庫查詢都是並行執行的 - 不需要其中一個等待另一個。代碼簡短易讀 - 實際上在問題本身中發佈的希望「非工作示例」的長度和複雜性(或者說缺乏)相當。

承諾是很酷的。使用它們。