2012-11-04 99 views
2

我有從node.js異步查詢mongodb的問題。這裏是我的代碼在node.js和mongodb中處理異步數據庫查詢

var values = []; 
var positives = new Array(); 
var negatives = new Array(); 

var server1 = new mongodb.Server('localhost',27017, {auto_reconnect: true}); 
var db1 = new mongodb.Db('clicker', server1); 

db1.open(function(err, db) { 
    if(!err) { 

     db1.collection('feedback', function(err, collection) { 
      for (var i=0;i <5; i++) { 
       collection.find(
        {value:1}, 
        {created_on: 
         {  
          $gte:startTime + (i*60*1000 - 30*1000), 
          $lt: startTime + (i*60*1000 + 30*1000) 
         } 
        }, 
        function(err_positive, result_positive) { 
         result_positive.count(function(err, count){ 
           console.log("Total matches: " + count); 
           positives[i] = count; 
         }); 
        } 

       );    

       collection.find(
        {value:0}, 
        {created_on: 
         { 
          $gte:startTime + (i*60*1000 - 30*1000), 
          $lt: startTime + (i*60*1000 + 30*1000) 
         } 
        }, 
        function(err_negative, result_negative) { 
         result_negative.count(function(err, count){ 
           console.log("Total matches: " + count); 
           negatives[i] = count; 
         }); 
        } 
       );         
      } 

     }); 

    } else { 
     console.log('Error connecting to the database'); 
    }  

}); 

其實,我試圖從數據庫中獲取一些值。然後我需要操縱這些值。這只是我需要從正計數中減去負計數,然後使用positivecount-negative計數初始化值數組。現在因爲結果是異步獲得的。我該如何操作這些值並將它們放入值數組中。

+1

歡迎來到node.js簡單的控制流變得困難。 – usr

回答

10

在我進一步解釋,我想注意,在你的代碼中的錯誤:&循環問題

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 
} 

經典關閉。請參閱:Please explain the use of JavaScript closures in loops

現在,如何處理循環中的異步函數。基本思想是,您需要跟蹤已完成的異步調用的數量,並在最終調用返回時運行代碼。例如:

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這種「等待換所有到完整的」邏輯:Coordinating parallel execution in node.js

但由於我們使用Node.js的,我們可以使用便捷的異步模塊形式NPM:https://npmjs.org/package/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); 
}); 
+0

+1爲異步模塊:) –