MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Gestion des requêtes de base de données asynchrones dans node.js et mongodb

Avant d'expliquer davantage, j'aimerais noter qu'il y a un bogue dans votre code :

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
}

Problème de fermetures &boucles classiques. Voir :Veuillez expliquer l'utilisation des fermetures JavaScript dans les boucles

Maintenant, comment gérer les fonctions asynchrones dans les boucles. L'idée de base est que vous devez suivre le nombre d'appels asynchrones terminés et exécuter votre code une fois l'appel final renvoyé. Par exemple :

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)
  ); 
}

Cependant, si nous continuons à faire cela, il est évident que nous finirons par créer un tas de variables temporaires et nous retrouverons avec un code horriblement imbriqué. Mais ceci étant du javascript, nous pouvons encapsuler la logique de ce modèle dans une fonction. Voici mon implémentation de cette logique "wait-for-all-to-complete" en javascript :Coordonner l'exécution parallèle dans node.js

Mais puisque nous utilisons node.js, nous pouvons utiliser le formulaire de module asynchrone pratique npm :https://npmjs .org/package/async

Avec async, vous pouvez écrire votre code comme ceci :

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);
});