2014-08-31 3 views
1

Node/MongoDB를 사용하여 삽입하고 연결하고 있지만 범위 문제로 인해 함수에서 연결에 액세스 할 수 없습니다. 'db'변수를 전역 범위로 만드는 방법에 대한 아이디어가 있습니까? 우선MongoDB/Javascript Scope 문제

mongodb.connect("mongodb://localhost:27017/userDB", function(err, db) { 

    if(!err) { 
     console.log("We are connected"); 
    } else { 
     console.log(err); 
    } 

}); 

function RegisterUser(user, pass) { 
    var collection = db.collection('users'); 
    var docs = [{username:user}, {password: pass}]; 
    collection.insert(docs, {w:1}, function(err, result) { 
     collection.find().toArray(function(err, items) {}); 
     socket.emit('message', items); 
    }); 
} 

/var/www/baseball/app.js:80 
    var collection = db.collection('users'); <--db is not defined 
        ^
ReferenceError: db is not defined 
at RegisterUser (/var/www/baseball/app.js:80:20) 
at ParseData (/var/www/baseball/app.js:63:6) 

답변

1

는 한 번만 연결을 dB로 매개 변수를 전달해야합니다 아마 당신이 응용 프로그램을 시작합니다. mongo 운전자는 적어도 풀링 등을 처리 할 것이므로 몽고 랩 (MongoLabs)의 전문가들에 의해 들었다. 이것은 Java 등에서하는 작업과 매우 다르다는 점에 유의하십시오. connect()가 반환 한 db 값을 어딘가에 저장하거나, 전역 또는 응용 프로그램 또는 일반적으로 사용되는 모듈에 저장하십시오. 그런 다음 RegisterUser, DeleteUser 등에서 필요에 따라 사용하십시오.

+0

내 잘못, 방금 전역 var global_db 콜백 외부에 선언했다. 나는 그것을 시도하고 일을하지 않았지만 다시 시도해 보니 감사하다고 생각했습니다. –

+0

장기적으로 닐의 대답처럼 좀 더 정교한 작업을해야 할 필요가있을 수 있습니다. 그러나 글로벌 작업이 필요하지는 않지만 적어도 시작되었습니다. – user949300

0

, 당신은 그렇게도 당신이 거기에해야 할 일을 일을 ... 그래서 연결 범위 내에서 RegisterUser 전화, 일단 접속이되면 사용자를 등록 할 것입니다. 그 함수 내에서 DB 객체를 사용하려는 경우 다음 함수 내에서 DB를 사용할 수 있습니다

RegisterUsers(db, user, pass)

당신은 일반적으로

1

노드 질문에 대한 많은 내용이 있지만 실제로는 태그의 가치가 있습니다. 따라서 범위가 지정된 문제가 있으며 변수가 .connect() 메서드의 콜백 함수에 대해 로컬이므로 다른 곳에서는 볼 수 없으므로 올바른 것으로 나타났습니다. 한 가지 방법은 해당 콜백 내에 모든 논리를 덤프하는 것이므로 범위 지정 문제는 없지만 그렇게하고 싶지는 않을 것입니다.

"어떻게 글로벌을 설정합니까?"라는 질문은 올바른 접근 방식이 아닙니다. 노드의 "비동기"패턴을 깨는 것에 대해 일반적인 재미있는 것들이 있기 때문에 직접적으로는 좋지 않습니다. 따라서 더 나은 접근법은 연결을 한 번만 설정하는 것과 같은 일종의 "싱글 톤"인스턴스를 사용하는 것입니다. 그러나이 연결은 전역 적이거나 그렇지 않으면 응용 프로그램의 다른 영역에서 사용하기 위해 "필요"할 수 있습니다. 여기

가 입증 한 "사소한"접근 방식이지만,이 같은 일을 수행하는 방법은 여러 가지이다 : 그것은 또한

var async = require('async'), 
    mongodb = require('mongodb'), 
    MongoClient = mongodb.MongoClient; 


var Model = (function() { 

    var _db; 
    var conlock; 
    return { 
    getDb: function(callback) { 
     var err = null; 
     if (_db == null && conlock == null) { 
     conlock = 1; 
     MongoClient.connect('mongodb://localhost/test',function(err,db) { 
      _db = db; 
      conlock == null; 
      if (!err) { 
      console.log("Connected") 
      } 
      callback(err,_db); 
     }); 
     } else if (conlock != null) { 
     var count = 0; 
     async.whilst(
      function() { return (_db == null) && (count < 5) }, 
      function(callback) { 
      count++ 
      setTimeout(callback,500); 
      }, 
      function(err) { 
      if (count == 5) 
       err = new Error("connect wait exceeded"); 
      callback(err,_db); 
      } 
     ); 
     } else { 
     callback(err,_db); 
     } 
    } 
    }; 

})(); 


async.parallel(
    [ 
    function(callback) { 
     console.log("call model"); 
     Model.getDb(function(err,db) { 
     if (err) throw err; 
     if (db != undefined) 
      console.log("db is defined"); 
     callback(); 
     }); 
    }, 
    function(callback) { 
     console.log("call model again"); 
     Model.getDb(function(err,db) { 
     if (err) throw err; 
     if (db != undefined) 
      console.log("db is defined here as well"); 
     callback(); 
     }) 
    } 
    ], 
    function(err) { 
    Model.getDb(function(err,db) { 
     db.close(); 
    }); 
    } 
); 

그래서 밖으로 작은 "모델"개체가 여기 .getDb()에서 하나의 방법이있다, 그리고 일단 그것이 성립되면 _db 연결을 유지하는 개인 변수를 유지합니다. 이 방법의 기본 논리는 _db이 정의되어 있는지 확인한 다음 드라이버와의 연결을 설정하지 않는 것입니다. 그런 다음 연결 콜백에서 _db 변수가 설정됩니다.

다른 방법은 메서드 자체가 "콜백"을 받아들이므로 나중에 오류나 현재 연결이 반환되는 방식입니다.

마지막 부분은 코드에서 구현되는 두 가지 기능에 대한 데모입니다. 첫 번째 호출에서 데이터베이스에 연결하는 호출은 제공된 콜백 함수로 이어지기 전에 수행됩니다.

다음 번에 우리가 호출 할 때 연결이 개인 변수에 이미 설정되어 있으므로 데이터가 반환되고 사용자가 다시 연결하지 않습니다.

이런 종류의 작업을 구현하는 방법은 다양하지만, 그 기본 논리 패턴을 따라야합니다. MongoDB 드라이버를 감싸는 여러 가지 "도우미"구현이있어 이런 종류의 작업을 단순하게 할뿐만 아니라 연결 풀을 관리하고 연결이 잘되어 있는지 확인할 수 있습니다. 낮은 수준의 드라이버 기반에서 모든 일을 스스로하는 것에 여전히 강요합니다.

+0

답변 # 1의 주석을 참조하십시오. 자세한 노력은 고맙겠지 만 콜백 외부에서 전역 (윈도우) 변수를 선언하고 해당 전역 변수와 동일한 로컬 db 객체를 설정하는 것만 큼 간단합니다. 감사. –

+0

@ TheHawk 데이터베이스가 아직 연결되어 있지 않은 경우 프로덕션 응용 프로그램이 시작된 직후에 URL에서 히트를 수신하면 불만을 나타냅니다. 몇 초 만에 글로벌이 선언되지만 그렇지 않은 경우에는 선언되지 않습니다. 이것이 당신이 누락 된 요점입니다. –

+0

@ Neeil 유효한 포인트,하지만 만약 내가 _think_ 일찍 2 히트를 얻을 코드는 2 개의 연결을 열 것인가? 이것을하기위한 표준 "제조법"이 있어야하는 것처럼 보입니다. – user949300

관련 문제