详解Node.js模块间共享数据库连接的方法


Posted in Javascript onMay 24, 2016

这个标题本身就是一个命题,因为使用默认方式的情况下,一个 Node.js 应用里的各个模块都是共享的同一个数据库连接。但是如果姿势不对,可能会很丑陋,甚至可能会出错。

你可以忽略下面这部分,直接切入正题。

背景
最近在做专业课程设计,题目是“机票预订管理系统”。需求比较简单,就试着拿最近在学的 Node.js 来做了。本来还在调研用何种 Node.js 框架比较合适,看了几个框架之后发现这是杀鸡用牛刀,有看文档查资料的时间还不如直接动手写了。最后写完我会把代码放到 Github 上,欢迎大家批评指正。

数据库方面,以为我比较熟悉和喜欢 JSON (SQL 没学好就承认呗-_-#),所以就选择了 MongoDB。Node + Mongo 是近几年越来越热门的后端组合,网上有很多关于如何一起使用的资料。但为了节约时间(课程设计也就一个多星期),把精力多集中在系统和逻辑上,我用了 Mongoose 这个专门用于 MongoDB 数据建模的 Node.js 扩展,用它来大大减少操作数据库的代码。

正题
我建立了两个数据模型(Model),一个是用户(User),一个是航班(Flight),分别封装到了 user.js, flight.js 这两个模块(Module)里面。Model 专门负责和数据库交互,用户和航班这两个模块都需要连接数据库,一开始我的代码是这样的:

// ----- user.js -----
// require mongoose.js 引用mongoose.js
var M = require('mongoose');
// connect to database 连接数据库
M.connect('mongodb://localhost/test');
// ... some other code ...

// ----- flight.js -----
// require mongoose.js 引用mongoose.js
var M = require('mongoose');
// connect to database 连接数据库
M.connect('mongodb://localhost/test');
// ... some other code ...

// ----- models.js -----
var user = require('./user'),
  flight = require('./flight');

// ----- index.js -----
var Models = require('./models');

且不说这种写法一点都不 DRY,这种方式本身就是错误的。当我运行 index.js 时,会出现如下错误。

> node index.js
> Connection error: { [Error: Trying to open unclosed connection.] state: 2 }

错误是:尝试打开未关闭的连接。

所以我们应该在一个地方连接一次数据库,然后其他需要连接数据库的模块通过这个模块来和数据库交互。就好像插线板,义无反顾地吼叫道:“墙上就一个插座,你们不要抢了!放着我来!你们。。。就可以了!”

具体方案
我们把连接数据库的动作放到一个模块里,并且把连接暴露给整个应用中的其他模块,然后其他需要连接数据库的模块引用这个连接即可。

// ----- database.js -----
var M = require('mongoose');
M.connect('mongodb://localhost/test');
// reference to the database connection 为这个连接创建一个引用
var db = M.connection;
// expose to modules that require database.js 把这个引用暴露给引用 database 模块的其他模块
module.exports = db;

// ----- user.js ----- flight.js 类似 -----
// ... some other code ...
// 我们会在 models.js 中,把数据库连接的引用作为参数传进来
module.exports = function( db ){
  if( db ){
    // ... do things with the connection ... 如果连接了数据库,就可以执行数据库相关的操作了
  }
}

// ----- models.js -----
// require database module, retrieve the reference to database connection 引用 databse 模块,获取数据库连接的引用
var db = require('./database');
// 把数据库连接的引用传入需要连接数据库的模块,任务完成!
var user = require('./user')( db ),
  flight = require('./flight')( db );

这就是让一个 Node.js 应用的多个模块共享数据库连接的一种方法。是我在 StackOverflow 上面看到的。如果你有更好的方法,欢迎在评论中分享给大家!

Javascript 相关文章推荐
javascript Ext JS 状态默认存储时间
Feb 15 Javascript
JQuery jsonp 使用示例代码
Aug 12 Javascript
JavaScript NodeTree导航栏(菜单项JSON类型/自制)
Feb 01 Javascript
文本框回车提交与禁止提交示例
Sep 27 Javascript
yui3的AOP(面向切面编程)和OOP(面向对象编程)
May 01 Javascript
jQuery实现简单的滑动导航代码(移动端)
May 22 jQuery
浅谈Node Inspector 代理实现
Oct 19 Javascript
angularjs使用gulp-uglify压缩后执行报错的解决方法
Mar 07 Javascript
JavaScript循环遍历你会用哪些之小结篇
Sep 28 Javascript
分享Angular http interceptors 拦截器使用(推荐)
Nov 10 Javascript
Vue Render函数原理及代码实例解析
Jul 30 Javascript
微信小程序实现拼图小游戏
Oct 22 Javascript
轻松掌握jQuery中wrap()与unwrap()函数的用法
May 24 #Javascript
使用jQuery中的wrap()函数操作HTML元素的教程
May 24 #Javascript
实例解析jQuery中proxy()函数的用法
May 24 #Javascript
jQuery前端开发35个小技巧
May 24 #Javascript
JS+Canvas绘制时钟效果
Aug 20 #Javascript
基于JQuery实现图片上传预览与删除操作
May 24 #Javascript
JavaScript仿淘宝页面图片滚动加载及刷新回顶部的方法解析
May 24 #Javascript
You might like
php数组函数序列之array_flip() 将数组键名与值对调
2011/11/07 PHP
Symfony2实现在controller中获取url的方法
2016/03/18 PHP
Thinkphp通过一个入口文件如何区分移动端和PC端
2017/04/18 PHP
php JWT在web端中的使用方法教程
2018/09/06 PHP
js获取html参数及向swf传递参数应用介绍
2013/02/18 Javascript
如何在指定的地方插入html内容和文本内容
2013/12/23 Javascript
JavaScript获取两个数组交集的方法
2015/06/09 Javascript
原生js实现class的添加和删除简单代码
2016/07/12 Javascript
详解Angular中$cacheFactory缓存的使用
2016/08/19 Javascript
vue2.0+webpack环境的构造过程
2016/11/08 Javascript
bootstrap实现图片自动轮播
2016/12/21 Javascript
如何使用angularJs
2017/05/08 Javascript
jquery中ajax请求后台数据成功后既不执行success也不执行error的完美解决方法
2017/12/24 jQuery
JS实现的倒计时恢复按钮点击功能【可用于协议阅读倒计时】
2018/04/19 Javascript
Vue 去除路径中的#号
2018/04/19 Javascript
vue如何自动化打包测试环境和正式环境的dist/test文件
2019/06/06 Javascript
9种方法优化jQuery代码详解
2020/02/04 jQuery
vue实现图片按比例缩放问题操作
2020/08/11 Javascript
[04:12]第二届DOTA2亚洲邀请赛选手传记-Newbee.Sccc
2017/04/03 DOTA
python 合并文件的具体实例
2013/08/08 Python
跟老齐学Python之有容乃大的list(3)
2014/09/15 Python
Python+tkinter使用40行代码实现计算器功能
2018/01/30 Python
python 提取文件指定列的方法示例
2019/08/07 Python
在pytorch中为Module和Tensor指定GPU的例子
2019/08/19 Python
如何将 awk 脚本移植到 Python
2019/12/09 Python
python interpolate插值实例
2020/07/06 Python
英国家电直销:Appliances Direct
2016/09/22 全球购物
Ego Shoes官网:英国时髦鞋类品牌
2020/10/19 全球购物
医学院护理专业应届生求职信
2013/11/12 职场文书
市场开发与营销专业求职信
2013/12/31 职场文书
给交警的表扬信
2014/01/12 职场文书
英语商务邀请函范文
2014/01/16 职场文书
2015年领导班子工作总结
2015/05/23 职场文书
业务员管理制度范本
2015/08/06 职场文书
餐厅如何利用“营销策略”扭转亏本局面
2019/10/15 职场文书
Laravel中获取IP的真实地理位置
2021/04/01 PHP