nodejs中如何同步连接mongodb

Posted

技术标签:

【中文标题】nodejs中如何同步连接mongodb【英文标题】:how to connect to mongodb synchronously in nodejs 【发布时间】:2016-09-05 22:10:50 【问题描述】:

我想利用 Promise 功能,我可以同步连接到 mongodb,并且可以通过将连接传递给不同的模块来重用连接。

这是我想出的东西

class MongoDB 

    constructor(db,collection)       
      this.collection = db.collection(collection);
    

    find(query, projection) 
        if(projection)
            return this.collection.find(query, projection);
        else
            return this.collection.find(query);
    


class Crew extends MongoDB 

    constructor(db)         
        super(db,'crews');
    

    validate() 

    

我想在我的初始代码中的某处设置一个连接,如下面的那个,然后将连接重用于不同的类,就像猫鼬或僧侣所做的那样,但只使用 node-mongodb-native 包。

MongoClient.connect(url)
          .then( (err,dbase) => 
                global.DB = dbase;
              );


var Crew = new CrewModel(global.DB);


Crew.find()
   .then(function(resp) 
      console.log(resp);
   );

现在,db 在主要的 MongoDB 类中返回 undefined,并且无法通过 google 或文档对其进行调试。

编辑:我曾假设承诺是同步的,但事实并非如此。

【问题讨论】:

【参考方案1】:

我一直在努力解决这个问题,特别是在跨调用的 AWS lambda 函数中设置和持久化 MongoDb 连接。 感谢@toszter 的回答,我终于想出了以下解决方案:

const mongodb = require('mongodb');
const config  = require('./config.json')[env];
const client  = mongodb.MongoClient;

const mongodbUri = `mongodb://$config.mongo.user:$config.mongo.password@$config.mongo.url/$config.mongo.database`;


const options = 
  poolSize: 100, 
  connectTimeoutMS: 120000, 
  socketTimeoutMS: 1440000
 ;

// connection object
let _db = null;

class MongoDBConnection 
  constructor() 

  // return a promise to the existing connection or the connection function
  getDB() 
    return (_db ? Promise.resolve(_db) : mConnect());
  


module.exports = new MongoDBConnection();

// transforms into a promise Mongo's client.connect
function mConnect() 
  return new Promise((resolve, reject) => 
    console.log('Connecting to Mongo...');
    client.connect(mongodbUri, options, (error, db) => 
      if (error)  
        _db = null;
        return reject(error);
      
      else 
        console.log('Connected to Mongo...');
        _db = db;
        resolve(db);
      
    );
  );

在控制器或 app.js 中使用它:

  const mongoConfig  =  require('mongoConfig');
  mongoConfig.getDB()
    .then(db => db.collection('collection').find())
    .catch(error => ...);

【讨论】:

【参考方案2】:

使用 ES6 类的另一个选项创建一个可以重复访问的单例对象。它的灵感来自@user3134009 的回答here。

const EventEmitter = require('events');
const MongoClient = require('mongodb').MongoClient;
const config = require('config');

let _db = null;

class MongoDBConnection extends EventEmitter 
  constructor() 
    super();
    this.emit("dbinit", this);
    if (_db == null) 
      console.log("Connecting to MongoDB...");
      MongoClient.connect(config.dbs.mongo.url, config.dbs.mongo.options, 
(err, db) => 
        if (err) 
           console.error("MongoDB Connection Error", err);
          _db = null;
         else 
          console.log("Connected to MongoDB", config.dbs.mongo.url);
          db.on('close', () =>  console.log("MongoDB closed", arguments); _db = null; );
          db.on('reconnect', () =>  console.log("MongoDB reconnected", arguments); _db = db; );
          db.on('timeout', () =>  console.log("MongoDB timeout", arguments); );
          _db = db;
          this.emit('dbconnect', _db);
        
      );
    
  
  getDB() 
    return _db;
  

module.exports = new MongoDBConnection();

【讨论】:

【参考方案3】:

要重用连接,我会创建一个这样的模块。

module.exports = 

    connect: function(dbName,  callback ) 
       MongoClient.connect(dbName, function(err, db) 

       _db = db;
       return callback( err );
    );
,

     getDb: function() 
        return _db;
     
;

之后,您可以在启动应用程序之前连接到数据库

MongoConnection.connect("mongodb://localhost:27017/myDatabase", function(err)
    app.listen(3000, function () 
        // you code
    );
);

考虑到您在 js 文件中创建了模块,您可以简单地使用 require 来获取数据库连接

var dbConnection = require("./myMongoConnection.js");

并获得连接使用

var db = MongoConnection.getDb();

【讨论】:

谢谢,我的问题有问题。我假设一个承诺是同步的,因此我的代码中有一些错误,但感谢这条信息,因为它对我非常有用。

以上是关于nodejs中如何同步连接mongodb的主要内容,如果未能解决你的问题,请参考以下文章

如何在nodejs中结合同步和异步功能

如何在同步nodejs函数中等待promise?

如何在nodejs中获得同步readline,或使用异步“模拟”它?

如何使用 NodeJS 同步运行两个函数?

记阿里面试的一道nodejs中http同步处理请求问题

记阿里面试的一道nodejs中http同步处理请求问题