2012-11-04 5 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'); 
    }  

}); 

사실, 데이터베이스에서 일부 값을 가져 오려고합니다. 그리고 나서이 값들을 조작해야합니다. 그것은 단지 내가 양수 계산에서 음수를 뺀 다음 양수 음수로 값 배열을 초기화해야한다는 것입니다. 이제 결과가 비동기 적으로 얻어지기 때문에 어떻게 그 값을 조작하여 값 배열에 넣어야합니까?

+1

간단한 제어 흐름이 어려워지는 것을 환영합니다. – 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) 
); 
} 

우리가이 일을 계속한다면, 우리가 임시 변수의 무리를 만들어 결국 끔찍하게 중첩 된 코드로 오게 분명하다. 하지만이 자바 스크립트, 우리는이 패턴에 대한 논리를 함수에 캡슐화 할 수 있습니다. 여기에 자바 스크립트에서이 "대기 -에 대한 - 모든-에 완성"논리의 내 구현의 : Coordinating parallel execution in node.js

그러나 우리는 Node.js를를 사용하고 있기 때문에, 우리는 편리 비동기 모듈 형태의 NPM 사용할 수 있습니다 https://npmjs.org/package/async

을 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 for async module :) –