详解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 相关文章推荐
jQuery实现炫酷的鼠标轨迹特效
Feb 01 Javascript
jQuery 获取屏幕高度、宽度的简单实现案例
May 17 Javascript
JavaScript比较当前时间是否在指定时间段内的方法
Aug 02 Javascript
JS数组排序方法实例分析
Dec 16 Javascript
Angularjs实现分页和分页算法的示例代码
Dec 23 Javascript
利用nginx + node在阿里云部署https的步骤详解
Dec 19 Javascript
基于JavaScript中标识符的命名规则介绍
Jan 06 Javascript
JS脚本加载后执行相应回调函数的操作方法
Feb 28 Javascript
vue 父组件调用子组件方法及事件
Mar 29 Javascript
vue中promise的使用及异步请求数据的方法
Nov 08 Javascript
js canvas实现二维码和图片合成的海报
Nov 19 Javascript
p5.js码绘“跳动的小正方形”的实现代码
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来检测proxy
2006/10/09 PHP
ThinkPHP字符串函数及常用函数汇总
2014/07/18 PHP
php日期操作技巧小结
2016/06/25 PHP
Laravel实现ORM带条件搜索分页
2019/10/24 PHP
网站页面自动跳转实现方法PHP、JSP(上)
2010/08/01 Javascript
JavaScript高级程序设计 XML、Ajax 学习笔记
2011/09/10 Javascript
JavaScript 盒模型 尺寸深入理解
2012/12/31 Javascript
chrome下jq width()方法取值为0的解决方法
2014/05/26 Javascript
Web表单提交之disabled问题js解决方法
2015/01/13 Javascript
实例讲解js验证表单项是否为空的方法
2016/01/09 Javascript
基于jQuery的AJAX和JSON实现纯html数据模板
2016/08/09 Javascript
angularJs关于指令的一些冷门属性详解
2016/10/24 Javascript
JavaScript实现滑动导航栏效果
2017/08/30 Javascript
bootstrap里bootstrap动态加载下拉框的实例讲解
2018/08/10 Javascript
Vue实现远程获取路由与页面刷新导致404错误的解决
2019/01/31 Javascript
小程序getLocation需要在app.json中声明permission字段
2019/04/04 Javascript
es6 for循环中let和var区别详解
2020/01/12 Javascript
Node.js API详解之 zlib模块用法分析
2020/05/19 Javascript
使用Element的InfiniteScroll 无限滚动组件报错的解决
2020/07/27 Javascript
[02:51]DOTA2 2015国际邀请赛中国区预选赛第一日战报
2015/05/27 DOTA
Python greenlet实现原理和使用示例
2014/09/24 Python
解决Python字典写入文件出行首行有空格的问题
2017/09/27 Python
Python自然语言处理之词干,词形与最大匹配算法代码详解
2017/11/16 Python
Python Tkinter 简单登录界面的实现
2019/06/14 Python
python不相等的两个字符串的 if 条件判断为True详解
2020/03/12 Python
使用CSS3的::selection改变选中文本颜色的方法
2015/09/29 HTML / CSS
css3实现蒙版弹幕功能
2019/06/18 HTML / CSS
布鲁明戴尔百货店:Bloomingdale’s
2016/12/21 全球购物
如何查找网页漏洞
2016/06/22 面试题
大学中国梦演讲稿
2014/04/23 职场文书
软件售后服务承诺书
2014/05/21 职场文书
活动总结结尾怎么写
2014/08/30 职场文书
党员干部群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
给老师的感谢信
2015/01/20 职场文书
幼儿园秋季开学通知
2015/07/16 职场文书
500字作文之周记
2019/12/13 职场文书