异步mongodb在返回所有数据之前在循环内完成查找

时间:2014-11-08 21:39:49

标签: javascript node.js mongodb asynchronous

我正在使用Async实用程序模块从Mongodb数据库返回项目。我想异步做。我在尝试归还这些物品时遇到了问题。

我想在所有User.find()'s完成之后触发回调,现在async.each()提前终止,并且只在数据库应该返回所有项目时给我一个项目

代码如下:

async.each(lessons, function(lesson, next) { // For each item in lesson array
    if (_.isEmpty(lesson.lesson_grades) == true) { // Check if the grades array is empty
        return;
    } else {
        async.each(lesson.lesson_grades, function(grade, next) { // For each grade in grade array
            User.find({ // Find user from grade user_id
                _id: grade.user_id,
            }, '-salt -hashedPassword', function(err, user) {

                grade["name"] = user[0].name; // Add name
                grade["email"] = user[0].email; // Add email

                next(); // !! I think this is where the problem lies, it fires next() once the first item has been returned - so it doesn't get to the other items !!
            });
        }, function(err) {
            next(lessons);
        });
    }
}, function(lessons, err) {
    return res.json(200, lessons); // Return modified lessons (with name and email) to browser, currently only returns one but returns them all if a setTimeout() is added, making it a premature callback problem
});

有人能指出我正确的方向如何正确地做到这一点?我应该跟踪迭代吗?任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

异步后面的约定是回调函数有两个参数:错误和结果,按顺序。错误和结果之间的区别很重要,因为异步会在收到错误时立即完成。说function(err) { next(lessons); }的部分是错误的 - 异步错误地将lessons误解为错误,因为它是真的。它应该是:

function(err, result) {
    next(err, result);
}

或者实际上你可以用next替换函数。

此外,接近结尾function(lessons, error)应为function(error)

需要注意的另一件事是:您必须确保每次回调只调用一次。但是如果它运行if块而不是else块,则永远不会调用next;异步永远不会完成。它不会阻止其他代码运行,但它永远不会到达return res.json(200, lessons);。 (它也可能泄漏记忆,我不确定。)

最后一件事:在回调中返回结果将不会做任何事情。看起来你试图从同步函数调用所有这些异步代码;这不起作用。将调用res.json,但如果它返回一个值,那么您可能希望将该值用作来自其他地方的另一个回调函数的参数。但是我需要更多关于你要做什么的信息。