2012-11-04 78 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为异步模块:) –