ページをマングースの結果でレンディングするために見つけることができるものはすべて、このようにすることを言っています:
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
});
これはできますか?
同期パラダイムを強制しようとしています。うまくいきません。 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
});
ネクロマンサーをここでプレイします。まだ別のより良い方法があります。
素晴らしいpromiseライブラリを使用する 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);
_
すべてのmongoose(およびそのモデル)メソッドを、Async
接尾辞(.exec()
が.execAsync()
になるなど)を使用して、promiseを返す関数として使用できるようにします。 .promisifyAll()
メソッドはNode.JSの世界ではほぼ普遍的です-コールバックを最後の引数として取得する非同期関数を提供するものなら何でも使用できます。
_Promise.props({
users: users.find().execAsync(),
articles: articles.find().execAsync()
})
_
.props()
bluebirdメソッドは、プロパティとしてpromiseを持つオブジェクトを受け取り、両方のデータベースクエリ(ここではpromise)が結果を返すときに解決される集合的なpromiseを返します。解決された値は、最終関数のresults
オブジェクトです。
results.users
_-mongooseによってデータベースで見つかったユーザーresults.articles
_-mongoose(d'uh)がデータベースで見つけた記事ご覧のとおり、インデントコールバックヘルに近づいていません。両方のデータベースクエリは並行して実行されます-どちらか一方が他方を待つ必要はありません。コードは短くて読みやすい-質問自体に投稿された希望的な「非動作例」に長さと複雑さ(またはむしろ欠如)で実際に対応しています。
約束はクールです。それらを使用します。
簡単な方法:
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 libraryのようなものを使用する必要があります。
しかし、あなたの場合、最も簡単な方法はコールバックをネストすることです(これにより、選択した以前のユーザーの記事を調べることができます)か、非同期ライブラリの助けを借りて完全に並行して行うことができます( フロー制御/非同期グッズ を参照してください)。
Node関数への戻り値としてかなり使用する関数があります。
function freturn (value, callback){
if(callback){
return callback(value);
}
return value;
};
次に、すべての署名にオプションのコールバックパラメーターがあります。
私は非常に似たものを扱っていましたが、クライアントからsocket.ioとDBアクセスを使用していました。私の発見は、データベースがデータを取得する機会を得る前に、私のデータベースの内容をクライアントに投げ返すことでした。
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);
});
});
したがって、この問題を解決するために、mongooseが提供する約束を使用し、DBからデータを受信すると、ソケットがクライアントにデータを送信します...
その価値のために...
次のコードで目的の結果を達成します。これがお役に立てば幸いです。
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);
});