MongoDB多个异步查询返回无序结果

时间:2015-10-04 22:57:38

标签: node.js mongodb asynchronous

我有一系列课程[course1,course2,...,courseN]。每个课程都有一个Hero UUID,它匹配另一个集合中对象的UUID。

// This is actually another db query but imagine it's an array

var courses = [{
    "courseName": "Sample course name 1",
    "hero": "a3f6f088-7b04-45e8-8d3b-d50c2d5b3a2d"
}, {
    "courseName": "Sample course name 2",
    "hero": "1b46227a-c496-43d2-be8e-1b0fa07cc94e"
}, {
    "courseName": "Sample course name 3",
    "hero": "c3bae6bf-2553-473a-9f30-f5c58c4fd608"
}];

我需要遍历所有课程,获取英雄uuid并对Heroes集合进行查询,然后在查询完成时将英雄信息添加到课程对象。

问题是所有查询都被快速触发,以至于MongoDB以任意顺序返回它们。它按顺序接收所有3个英雄uuids但有时会在第一个之前返回第三个,等等。有一种方法可以让一个查询完成然后再做另一个等等吗?

我现在正在做的是:

var newCourses = courses;
var counter = 0;

courses.forEach(function (course) {
    var courseHeroUuid = course.hero;
    // This function does the query by uuid and returns the doc
    getHeroByUuid(courseHeroUuid, function (err, result) {
        if (err) {
            next(err);
        }

        // Replace the hero UUID with the hero document itself
        newCourses[counter].hero = result[0];

        if (++counter == courses.length) {
            next(null, newCourses);
        }
    }
});

这是async.waterfall数组中的一个函数,这就是我跟踪计数器并调用next()继续运行的原因。我知道我可以使用async.each进行迭代,我试过它没有帮助。 这是我正在进行的查询。

function getHeroByUuid(heroUuid, callback) {
    Hero.find({uuid: heroUuid}, function (err, result) {
        if (err) {
            callback(err);
        }

        callback(null, result);
    })
}

发生这种情况: http://i.imgur.com/mEoQfgH.png

1 个答案:

答案 0 :(得分:0)

很抱歉回答我自己的问题,但我发现了。我需要的就是我的鼻子。

我最终使用了async.whilst()函数,文档是right here并完全按照我的需要执行 - 在返回前一个循环的结果后执行循环的下一次迭代。

我的代码现在看起来像这样:

var newCourses = courses;
var courseItemsLength = courses.length;
var counter = 0;

async.whilst(
    function () {
        return counter < courseItemsLength;
}, function (callback) {
    var heroUuid = allCourses[counter].hero;

    getHeroByUuid(heroUuid, function (err, result) {
        if (err) {
            next(err);
        }

        newCourses[counter].hero = result.name;

        counter++;
        if (err) {
            callback(err);
        }

        callback();
    });
}, function (err) {
    if (err) {
        next(err);
    }

    next(null, newCourses);
});