详解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 相关文章推荐
JS处理VBArray的函数使用说明
May 11 Javascript
js中关于new Object时传参的一些细节分析
Mar 13 Javascript
javascript简单事件处理和with用法介绍
Sep 16 Javascript
Jquery 动态循环输出表格具体方法
Nov 23 Javascript
js实现缓冲运动效果的方法
Apr 10 Javascript
基于BootStrap Metronic开发框架经验小结【九】实现Web页面内容的打印预览和保存操作
May 12 Javascript
EasyUI中的dataGrid的行内编辑
Jun 22 Javascript
vue中锚点的三种方法
Jul 06 Javascript
Next.js实现react服务器端渲染的方法示例
Jan 06 Javascript
在vue中动态添加class类进行显示隐藏实例
Nov 09 Javascript
JavaScript数组常用的增删改查与其他属性详解
Oct 13 Javascript
vuex中遇到的坑,vuex数据改变,组件中页面不渲染操作
Nov 16 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 cron中的批处理
2008/09/16 PHP
PHP 7.0.2 正式版发布
2016/01/08 PHP
关于PHP中协程和阻塞的一些理解与思考
2017/08/11 PHP
JavaScript this调用规则说明
2010/03/08 Javascript
javascript利用初始化数据装配模版的实现代码
2010/11/17 Javascript
读jQuery之十一 添加事件核心方法
2011/07/31 Javascript
Function.prototype.bind用法示例
2013/09/16 Javascript
JS判断、校验MAC地址的2个实例
2014/05/05 Javascript
Jquery技巧(必须掌握)
2016/03/16 Javascript
Bootstrap每天必学之工具提示(Tooltip)插件
2016/04/26 Javascript
JQuery为元素添加样式的实现方法
2016/07/20 Javascript
jQuery序列化后的表单值转换成Json
2017/06/16 jQuery
Vue的移动端多图上传插件vue-easy-uploader的示例代码
2017/11/27 Javascript
详解Angular路由之路由守卫
2018/05/10 Javascript
JavaScript实现一个带AI的井字棋游戏源码
2018/05/21 Javascript
详解Vue中组件的缓存
2019/04/20 Javascript
Node.js API详解之 module模块用法实例分析
2020/05/13 Javascript
Python进程间通信Queue实例解析
2018/01/25 Python
对Python 网络设备巡检脚本的实例讲解
2018/04/22 Python
使用Python监视指定目录下文件变更的方法
2018/10/15 Python
Python利用递归实现文件的复制方法
2018/10/27 Python
python导入坐标点的具体操作
2019/05/10 Python
scrapy实践之翻页爬取的实现
2021/01/05 Python
如何用css3实现switch组件开关的方法
2018/02/09 HTML / CSS
Doyoueven官网:澳大利亚健身服饰和配饰品牌
2019/03/24 全球购物
澳大利亚领先的优质葡萄酒拍卖会:Langton’s Fine Wines
2019/03/24 全球购物
远程学习的教学用品和家庭学习资源:Really Good Stuff
2020/04/27 全球购物
Weblogc domain问题
2014/01/27 面试题
校园报刊亭创业计划书
2014/01/02 职场文书
生日寿宴答谢词
2014/01/19 职场文书
水利水电专业自荐信
2014/07/08 职场文书
力学专业求职信
2014/07/23 职场文书
四风问题对照检查材料思想汇报
2014/10/07 职场文书
2015年社区纪检工作总结
2015/04/21 职场文书
2016大学生形势与政策心得体会
2016/01/12 职场文书
2016优秀护士求职自荐信
2016/01/28 职场文书