MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Umgang mit asynchronen Datenbankabfragen in node.js und mongodb

Bevor ich weiter erkläre, möchte ich darauf hinweisen, dass Ihr Code einen Fehler enthält:

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
}

Klassisches Problem mit Verschlüssen und Schlaufen. Siehe:Bitte Erläutern Sie die Verwendung von JavaScript-Abschlüssen in Schleifen

Nun, wie asynchrone Funktionen in Schleifen behandelt werden. Die Grundidee ist, dass Sie nachverfolgen müssen, wie viele asynchrone Aufrufe abgeschlossen wurden, und Ihren Code ausführen müssen, sobald der letzte Aufruf zurückkehrt. Zum Beispiel:

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

Wenn wir jedoch so weitermachen, ist es offensichtlich, dass wir am Ende eine Menge temporärer Variablen erstellen und mit schrecklich verschachteltem Code enden werden. Da dies jedoch Javascript ist, können wir die Logik für dieses Muster in einer Funktion kapseln. Hier ist meine Implementierung dieser "wait-for-all-to-complete"-Logik in Javascript:Koordinieren der parallelen Ausführung in node.js

Aber da wir node.js verwenden, können wir das bequeme Async-Modul von npm verwenden:https://npmjs .org/package/async

Mit async können Sie Ihren Code wie folgt schreiben:

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