2015-10-04 3 views
0

У меня есть набор курсов [course1, course2, ..., courseN]. Каждый курс имеет UUID героя, который соответствует UUID объекта в другой коллекции.MongoDB множественные async-запросы возвращают неупорядоченный результат

// 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, поэтому отслеживать счетчик и вызвать следующий(), чтобы идти дальше. Я знаю, что могу использовать 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

ответ

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