MongoDB/Javascript范围问题

MongoDB/Javascript范围问题,javascript,node.js,mongodb,node-mongodb-native,Javascript,Node.js,Mongodb,Node Mongodb Native,我正在连接Node/MongoDB并进行插入,但由于作用域问题,我无法从函数访问连接。知道如何使“db”变量成为全局范围吗 mongodb.connect("mongodb://localhost:27017/userDB", function(err, db) { if(!err) { console.log("We are connected"); } else { console.log(err); } }); function Regi

我正在连接Node/MongoDB并进行插入,但由于作用域问题,我无法从函数访问连接。知道如何使“db”变量成为全局范围吗

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)
mongodb.connect(“mongodb://localhost:27017/userDB,函数(err,db){
如果(!err){
log(“我们已连接”);
}否则{
控制台日志(err);
}
});
函数注册器(用户,通过){
var collection=db.collection(“用户”);
var docs=[{username:user},{password:pass}];
insert(docs,{w:1},函数(err,result){
collection.find().toArray(函数(err,items){});
发出('message',项);
});
}
/var/www/barball/app.js:80

var collection=db.collection(“用户”) 首先,你只有在建立了连接后才能注册用户,所以你需要在那里做些什么呢。。。因此,在连接范围内调用
RegisterUser
。如果要在该函数中使用db对象,则需要将参数作为db传入

RegisterUsers(数据库、用户、通行证)


然后,您可以在函数中使用db,一般情况下,只进行一次连接,可能是在应用程序启动时。mongo驱动程序将处理池等,至少,蒙古ABS的专家告诉我。请注意,这与您在Java中可能执行的操作非常不同,等等。。。将connect()返回的db值保存在某个位置,可能是全局或应用程序内,也可能是常用的模块中。然后根据需要在RegisterUser、DeleteUser等中使用它。

这实际上是一个节点问题,但可能值得一提,因为它会被询问一点。因此,您说存在范围问题,您是对的,因为变量是
.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();
    });
  }
);
var async=require('async'),
mongodb=require('mongodb'),
MongoClient=mongodb.MongoClient;
var模型=(函数(){
var_-db;
var-conlock;
返回{
getDb:函数(回调){
var err=null;
if(_db==null&&conlock==null){
conlock=1;
MongoClient.connect('mongodb://localhost/test,函数(err,db){
_db=db;
conlock==null;
如果(!err){
控制台日志(“已连接”)
}
回调(err,_db);
});
}else if(conlock!=null){
var计数=0;
异步的(
函数(){return(_db==null)&&(count<5)},
函数(回调){
计数++
setTimeout(回调,500);
},
功能(err){
如果(计数=5)
err=新错误(“超出连接等待”);
回调(err,_db);
}
);
}否则{
回调(err,_db);
}
}
};
})();
异步并行(
[
函数(回调){
log(“调用模型”);
Model.getDb(函数(err,db){
如果(错误)抛出错误;
如果(db!=未定义)
console.log(“定义了数据库”);
回调();
});
},
函数(回调){
log(“再次调用模型”);
Model.getDb(函数(err,db){
如果(错误)抛出错误;
如果(db!=未定义)
log(“这里也定义了db”);
回调();
})
}
],
功能(err){
Model.getDb(函数(err,db){
db.close();
});
}
);
因此,这里的out小“Model”对象在
.getDb()
中有一个方法,并且它还维护一个私有变量,在建立连接后保存
\u db
连接。该方法的基本逻辑是查看是否定义了
\u db
,以及在哪里没有与驱动程序建立连接。然后在连接回调上设置
\u db
变量

这里的另一件事是该方法本身接受一个“回调”,因此这就是您以后使用它的方式,其中将返回一个错误或当前连接

最后一部分只是要在代码中实现的两个函数的演示。其中,在第一次调用中,先调用连接到数据库的调用,然后再调用提供的回调函数

不过,下次调用时,连接已经在私有变量中设置好了,因此只返回数据,而不会再次建立连接


实现这类事情有多种方法,但这是要遵循的基本逻辑模式。还有许多其他的“帮助器”实现包装MongoDB驱动程序,使这些事情变得简单,管理连接池并确保连接对您来说也是正常的,因此,即使您仍然坚持自己从较低级别的驱动程序库中完成所有工作,也很值得一看。

My bad,我刚刚在回调之外声明了一个全局var global_db。我以为我试过了,但没用,但我又试了一次,真的成功了,谢谢。从长远来看,你可能需要做一些更复杂的事情,就像尼尔的回答一样,你可能不想要一个全球性的,但至少你已经开始了。见回答1中的评论。我很感谢您的详细工作,但它很简单,只需在回调外部声明一个全局(窗口)变量,并将本地db对象设置为该全局变量即可。谢谢