JS – Express – Mongoose在发送响应之前执行所有mongoose的承诺

我做一个论坛的API,其中一个论坛有很多的线程,线程有很多职位,职位可以有很多职位。

关系是这样完成的:

var PostSchema = new Schema({ text: String, authorId: String, slug: Number, posts: [{ type: Schema.Types.ObjectId, ref: 'Post'}], created: { type: Date, default: Date.now } }); 

父模型有一个儿子模型的ID列表。

我这样做了我的控制器:

 var util = require('util'), mongoose = require('mongoose'), Forum = mongoose.model('Forum'), Thread = mongoose.model('Thread'), Post = mongoose.model('Post'), async = require('async'); exports.show = function(req, res){ var forums; var getThreads = function(forum) { return forum.populate('threads', function(err, _forum){ if(err) throw new Error(err); forum.threads = _forum.threads; forum.threads.forEach(getPosts); return callback(err); }); }; var getPosts = function(thread) { return thread.populate('posts', function(err, _thread){ if(err) throw new Error(err); thread.posts = _thread.posts; thread.posts.forEach(getComments); return callback(err); }); }; var getComments = function(post) { return post.populate('posts', function(err, _post){ if(err) throw new Error(err); post.posts = _post.posts; post.posts.forEach(getComments); return callback(err); }); }; async.parallel([ function(callback) { return Forum.find({ ownerId: req.params.owner_id }).exec(function(err, _forums) { if(err) throw new Error(err); forums = _forums; forums.forEach(getThreads); return callback(err); }); } ], function(err){ res.json(forums); } ); }; 

我需要做出完整的论坛对象,然后使用这个响应,因为post有post,我不能只是做一个嵌套的填充。

我尝试使用asynchronous库,但它承诺之前执行callback函数。

我如何构build完整的论坛对象?

您需要以asynchronous方式正确处理您的树结构。 尝试这种方法:

(我没有testing过,但希望它能起作用)

 // ... var Forum = mongoose.model('Forum'); exports.show = function(req, res){ //Get the owner's forums Forum.find({ ownerId: req.params.owner_id }).exec(function(err, forums) { if(err) throw new Error(err); if(!forums.length) return response.json(forums); //Send an empty array if no forums where found //Build forums one by one var forum = forums.shift(); buildForum(forum, function () { forum = forums.shift(); if (forum) { buildForum(forum, this); } else { //All forums were built. res.json(forums); }; }); }); var buildForum = function (forum, onSuccess) { forum.populate('threads', function(err, forum){ if(err) throw new Error(err); if(!forum.threads.length) return onSuccess(); //Build threads one by one var threads = forum.threads; var thread = threads.shift(); buildThread(thread, function () { thread = threads.shift(); if (thread) { buildThread(thread, this); } else { //All threads were built. onSuccess(); }; }); }); }; var buildThread = function (thread, onSuccess) { thread.populate('posts', function(err, thread){ if(err) throw new Error(err); if(!thread.posts.length) return onSuccess(); //Build posts one by one var posts = thread.posts; var post = posts.shift(); buildPost(post, function () { post = posts.shift(); if (post) { buildPost(post, this); } else { //All posts were built. onSuccess(); }; }); }); }; var buildPost = function (post, onSuccess) { post.populate('posts', function(err, post){ if(err) throw new Error(err); if(!post.posts.length) return onSuccess(); //Build comments one by one var posts = post.posts; var _post = posts.shift(); buildPost(_post, function () { _post = posts.shift(); if (_post) { buildPost(_post, this); } else { //All comments were built. onSuccess(); }; }); }); }; }; 

这是我的解决scheme,只是在@Danypype解决scheme中的一个小修复。

 exports.show = function(req, res){ //Get the owner's forums Forum.find({ ownerId: req.params.owner_id }).exec(function(err, forums) { if(err) throw new Error(err); if(!forums.length) return response.json(forums); //Send an empty array if no forums where found //Build forums one by one var forum = forums.shift(); var responseForums = [forum]; buildForum(forum, function () { forum = forums.shift(); if (forum) { responseForums.push(forum); buildForum(forum, arguments.callee); } else { //All forums were built. res.json(responseForums); }; }); }); var buildForum = function (forum, onSuccess) { forum.populate('threads', function(err, forum){ if(err) throw new Error(err); if(!forum.threads.length) return onSuccess(); if(forum.length == 1) return onSuccess(); var thread = forum.threads.shift(); var responseThreads = [thread]; buildThread(thread, function () { thread = forum.threads.shift(); if (thread) { responseThreads.push(thread) buildThread(thread, arguments.callee); } else { //All threads were built. forum.threads = responseThreads; onSuccess(); }; }); }); }; var buildThread = function (thread, onSuccess) { thread.populate('posts', function(err, thread){ if(err) throw new Error(err); if(!thread.posts.length) return onSuccess(); var post = thread.posts.shift(); var responsePosts = [post] buildPost(post, function () { post = thread.posts.shift(); if (post) { responsePosts.push(post); buildPost(post, arguments.callee); } else { //All posts were built. thread.posts = responsePosts; onSuccess(); }; }); }); }; var buildPost = function (post, onSuccess) { post.populate('posts', function(err, post){ if(err) throw new Error(err); if(!post.posts.length) return onSuccess(); //Build comments one by one var _post = post.posts.shift(); var response_posts = [_post]; buildPost(_post, function () { _post = post.posts.shift(); if (_post) { response_posts.push(_post); buildPost(_post, arguments.callee); } else { //All comments were built. post.posts = response_posts; onSuccess(); }; }); }); }; };