Node.js设计模式:一次性创建数据库连接的模式

13

我希望你能帮助我设计一个在我的node.js应用程序中创建数据库连接的设计模式。

很显然可以这样做:

模块1:

var db;
exports.get_db = function(callback) {

  if (db == null) {
    dblibrary.create(connection_params, function(error, conn) {
      if (error == null) {
        db = conn;
        callback(null, db);
      }
    });
  } else {
    callback(null, db);
  }
};

模块2:

exports.do_something = function () {
  module1.get_db(function (err, conn) {
    if (err == null) {
      // continue using query
    }
  });
};

似乎对于每个想要获取数据库连接的人都要求使用回调函数进行惩罚是很痛苦的。

我可以这样做:

模块1:

var db;

dblibrary.create_connection(connection_params, function (err, conn) {

  if (err != null) {
     console.log("can't create connection");
     console.log(err);
     process.exit();
  } else {
     db = conn;
  }
});

exports.get_db = function() {
  return db;
};

这样做使得获取数据库连接变得简单快捷,但也意味着我们必须在节点启动时“等待”连接建立。
哪种设计更好?是否有更好的方法?
3个回答

8

mydb.js 模块:

var db
exports.db = function() {
    if (db === null) {
        db = dblibrary.createClient()
    }
    return db
}

其他模块:

var db = require('mydb').db()
...
db.query(...)

这个代码在启动时只创建一次数据库客户端实例。我喜欢这种解决方案,因为创建代码被封装在一个单独的模块中,其他模块可以通过一个require()语句访问该客户端。


4
如果 dblibrary 只有异步数据库创建功能,会发生什么?在理论上,存在一个很小的时间窗口,mydb.js 尚未完成创建,但主应用程序可能已经开始执行了,是吗? - MarcWan
@MarcWan 是的,这对于异步客户端创建是不起作用的(实际上这根本不起作用,不仅仅是理论上的问题)。我正在使用node_redis,它是同步的。但是,这段代码只在启动时运行一次。 - alienhard
2
你是否曾经担心你的应用程序只共享一个数据库连接?如果该连接被长时间运行的查询占用,那么你的应用程序的其余部分不会受到影响吗? - Anthony Webb
实际上,当你使用 var 定义一个变量但没有赋值时,你会得到一个 undefined 而不是 null,所以在这段代码中你总是会得到 undefined - alphakevin
一个错误的点击让我点了个踩,但是我无法取消:/ - RichieAHB

4

我看到的最佳答案是:

在 start.js 文件中:

    function init_done() {

      app.listen(8080);

    }


init_databases(init_done);

在databases.js文件中:

init_databases(init_done_cb) {

  db.create_async(/* connect data */ , function (err, res) {

    if (err == null) init_done_cb();

  });
}

这样就可以在没有尴尬/危险的等待期间异步启动数据库服务器。


你什么时候/如何断开连接? - Philipp Kyeck
不处理同时使用模型并需要数据库连接的命令行任务的情况。连接应在首次需要时创建,并保持到服务器关闭。 - deepwell
我不知道异步数据库的优势是什么,@marcWan你必须将连接变量设置为全局,这样其他模块才能轻松使用(不需要再使用require)。 - Ganesh Kumar

0

我写了connect-once来解决这类问题。这个模块实现了两个主要目标:

  1. 在请求到达之前应初始化连接
  2. 即使有多个请求同时到来,也应只初始化一次连接

你可以参考express-mongo-dbexpress-mongoose-db的使用示例。


我不明白这有什么帮助。示例代码仍然具有回调函数。 - Ian Warburton
@ian-warburton 的技巧是将传入的客户端放入等待状态,并在第一次创建连接时进行操作。如果客户端不断到来且已经请求了连接,则不做任何操作。回调函数在这里不是问题。 - floatdrop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接