Voordat ik verder uitleg, wil ik opmerken dat er een fout in uw code zit:
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
}
Klassiek probleem met sluitingen en lussen. Zie:Alsjeblieft het gebruik van JavaScript-sluitingen in lussen uitleggen
Nu, hoe om te gaan met asynchrone functies in lussen. Het basisidee is dat u moet bijhouden hoeveel asynchrone oproepen zijn voltooid en uw code moet uitvoeren zodra de laatste oproep terugkeert. Bijvoorbeeld:
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)
);
}
Als we dit echter blijven doen, is het duidelijk dat we uiteindelijk een heleboel tijdelijke variabelen zullen creëren en eindigen met vreselijk geneste code. Maar omdat dit javascript is, kunnen we de logica voor dit patroon in een functie inkapselen. Hier is mijn implementatie van deze "wait-for-all-to-complete" logica in javascript:Coördinatie van parallelle uitvoering in node.js
Maar aangezien we node.js gebruiken, kunnen we de handige async-module van npm gebruiken:https://npmjs .org/package/async
Met async kun je je code als volgt schrijven:
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);
});