mongoose(またはsequelize、redis)クエリの非同期性を指定すると、ビューをレンダリングする前に複数のクエリを作成する必要があります?express.jsのビューに複数のDB/mongooseクエリをレンダリングした結果
たとえば、セッションにuser_id
があり、その特定のユーザーに関する情報をfindOne
で取得したいとします。しかし、最近ログインしたユーザーのリストも表示する必要があります。
exports.index = function (req, res) {
var current_user = null
Player.find({last_logged_in : today()}).exec(function(err, players) {
if (err) return res.render('500');
if (req.session.user_id) {
Player.findOne({_id : req.session.user_id}).exec(function(err, player) {
if (err) return;
if (player) {
current_user = player
}
})
}
// here, current_user isn't populated until the callback fires
res.render('game/index', { title: 'Battle!',
players: players,
game_is_full: (players.length >= 6),
current_user: current_user
});
});
};
したがって、res.render
は最初のクエリコールバックにあります。しかし、私たちがこのユーザーを知っているかどうかを確認するために、findOne
からの応答を待つのはどうですか?条件付きで呼び出されるのは、render
を内側のコールバックの内側に置くことはできません。綺麗ではない。
私はいくつかの回避策を考えることができます -
それは本当に非同期にすると、現在のユーザーのプロファイルを取得するには、クライアント側のAJAXを使用しています。しかし、これは価値があるよりも多くの仕事のように思えます。
Q
を使用し、レンダリングする前にfindOne
クエリの解決を待つことを約束します。しかし、ある意味では、これはブロッキングが強制的に私の操作で応答を待たせるようなものです。正しいとは思わない。現在のユーザー情報を取得するためにミドルウェア機能を使用します。これはよりクリーンで、クエリを再利用可能にします。しかし、私はそれについてどうやって行くのか、それでも同じ問題が現れるかどうかはわかりません。
もちろん、より極端な場合には、作成するクエスチョンが十数個あれば、醜いものになる可能性があります。だから、このタイプの要件が与えられたときの通常のパターンは何ですか?
おかげで、十分に単純なようです。 'async.parallel'を使ってすべての結果をまとめるのはどうでしょうか?私はそれを試して、それは動作するようだが、それが良いアプローチかどうか疑問に思う。あなたのものは、はるかに難読化されています。 – sbeam
うん、 'async.parallel'はうまくいきません。おそらくあなたのユースケースに適したミドルウェアソリューションを含めるように答えを更新しました。 – JohnnyHK
nice、それは 'next()'との連鎖のおかげで再利用可能できれいです。 – sbeam