2013-12-18 3 views
1

Im делает форум api, где форум имеет много потоков, поток имеет много сообщений, и почта может иметь много сообщений.JS - Express - Mongoose выполнить все обещания мангуста перед отправкой ответа

Соотношения делается так:

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

Родитель модель имеет список идентификаторов сын модели.

Я сделал мой контроллер, как это:

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

}; 

Мне нужно сделал полный объект форума, а затем использовать это в ответ, поскольку сообщения имеют сообщение я не могу просто сделать вложенную Заполнить.

Я попытался использовать async lib, но он выполняет функцию обратного вызова перед обещаниями.

Как я могу построить полный объект форума?

ответ

1

Вам необходимо правильно обработать вашу древовидную структуру асинхронным способом. Попробуйте этот подход:

(я не проверял, но надеюсь, что он работает)

// ... 
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(); 
     }; 
     }); 
    }); 
    }; 
}; 
+0

Благодарим вас за ответ! Почти работа, я просто не знаю, как получить ответ. res.json (форумы); пусто. –

+0

@ user3117180 Вы отлаживаете правильно? Вы уверены, что не получаете пустой массив в качестве результата запроса базы данных? – danypype

+0

массив из db в порядке, но сдвиг просто удаляет все элементы массива, и в конце концов я не получаю ответа, –

1

Это мое решение, лишь незначительные фиксирует в растворе @Danypype.

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(); 
     }; 
     }); 
    }); 
    }; 
}; 
Смежные вопросы