Преди да обясня по-нататък, бих искал да отбележа, че във вашия код има грешка:
function(err_positive, result_positive) {
result_positive.count(function(err, count){
console.log("Total matches: " + count);
positives[i] = count; // <--- BUG: i id always 5 because it
}); // is captured in a closure
}
Проблем с класически затваряния и примки. Вижте:Моля обяснете използването на затваряния на JavaScript в цикли
Сега как да обработваме асинхронни функции в цикли. Основната идея е, че трябва да следите колко асинхронни извиквания са завършили и да стартирате кода си, след като последното повикване се върне. Например:
var END=5;
var counter=end;
for (var i=0;i<END; i++) {
collection.find(
{value:1},
{created_on:
{
$gte:startTime + (i*60*1000 - 30*1000),
$lt: startTime + (i*60*1000 + 30*1000)
}
},
(function(j){
return function(err_positive, result_positive) {
result_positive.count(function(err, count){
console.log("Total matches: " + count);
positives[j] = count;
});
counter--;
if (!counter) {
/*
* Last result, now we have all positives.
*
* Add code that need to process the result here.
*
*/
}
}
})(i)
);
}
Въпреки това, ако продължим да правим това, очевидно е, че в крайна сметка ще създадем куп временни променливи и ще се окажем с ужасно вложен код. Но тъй като това е javascript, можем да капсулираме логиката за този модел във функция. Ето моята реализация на тази логика „изчакване на всичко за завършване“ в javascript:Координиране на паралелно изпълнение в node.js
Но тъй като използваме node.js, можем да използваме удобната форма на асинхронен модул npm:https://npmjs .org/package/async
С async можете да напишете своя код по следния начин:
var queries = [];
// Build up queries:
for (var i=0;i <5; i++) {
queries.push((function(j){
return function(callback) {
collection.find(
{value:1},
{created_on:
{
$gte:startTime + (j*60*1000 - 30*1000),
$lt: startTime + (j*60*1000 + 30*1000)
}
},
function(err_positive, result_positive) {
result_positive.count(function(err, count){
console.log("Total matches: " + count);
positives[j] = count;
callback();
});
}
);
}
})(i));
queries.push((function(j){
return function(callback) {
collection.find(
{value:0},
{created_on:
{
$gte:startTime + (j*60*1000 - 30*1000),
$lt: startTime + (j*60*1000 + 30*1000)
}
},
function(err_negative, result_negative) {
result_negative.count(function(err, count){
console.log("Total matches: " + count);
negatives[j] = count;
callback();
});
}
);
}
})(i));
}
// Now execute the queries:
async.parallel(queries, function(){
// This function executes after all the queries have returned
// So we have access to the completed positives and negatives:
// For example, we can dump the arrays in Firebug:
console.log(positives,negatives);
});