详解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 相关文章推荐
flash 得到自身url参数的代码
Nov 15 Javascript
div层的移动及性能优化
Nov 16 Javascript
js 关于=+与+=日期函数使用说明(赋值运算符)
Nov 15 Javascript
javascript 中的事件委托详解
Oct 25 Javascript
JavaScript浏览器对象模型BOM(BrowserObjectModel)实例详解
Nov 29 Javascript
js禁止浏览器的回退事件
Apr 20 Javascript
React Native之TextInput组件解析示例
Aug 22 Javascript
jQuery菜单实例(全选,反选,取消)
Aug 28 jQuery
Angular父子组件通过服务传参的示例方法
Oct 31 Javascript
js与jquery获取input输入框中的值实例讲解
Feb 27 jQuery
JavaScript数组排序功能简单实现
May 14 Javascript
AutoJs实现刷宝短视频的思路详解
May 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
很实用的一个完整email发送程序
2006/10/09 PHP
PHP开发中四种查询返回结果分析
2011/01/02 PHP
抓取并下载CSS中所有图片文件的php代码
2011/09/26 PHP
Smarty中调用FCKeditor的方法
2014/10/27 PHP
PHP.ini安全配置检测工具pcc简单介绍
2015/07/02 PHP
php数据访问之查询关键字
2016/05/09 PHP
[原创]PHP正则删除html代码中a标签并保留标签内容的方法
2017/05/23 PHP
php快速导入大量数据的实例方法
2019/09/23 PHP
laravel 解决强制跳转 https的问题
2019/10/22 PHP
js利用div背景,做一个竖线的效果。
2008/11/22 Javascript
jquery动态加载js三种方法实例
2013/08/03 Javascript
兼容ie、firefox的图片自动缩放的css跟js代码分享
2013/08/12 Javascript
javascript使用window.open提示“已经计划系统关机”的原因
2014/08/15 Javascript
JS实现自适应高度表单文本框的方法
2015/02/25 Javascript
如何在Angular2中使用jQuery及其插件的方法
2017/02/09 Javascript
Angular.js中ng-include用法及多标签页面的实现方式详解
2017/05/07 Javascript
javascript将url解析为json格式的两种方法
2017/08/18 Javascript
Vue2 配置 Axios api 接口调用文件的方法
2017/11/13 Javascript
vue.js实现只弹一次弹框
2018/01/29 Javascript
监听angularJs列表数据是否渲染完毕的方法示例
2018/11/07 Javascript
微信小程序实现文字从右向左无限滚动
2020/11/18 Javascript
[01:14]3.19DOTA2发布会 三代刀塔人第二代
2014/03/25 DOTA
python3使用tkinter实现ui界面简单实例
2014/01/10 Python
Python的gevent框架的入门教程
2015/04/29 Python
Python使用字典的嵌套功能详解
2019/02/27 Python
python+selenium+chromedriver实现爬虫示例代码
2020/04/10 Python
Python 中如何使用 virtualenv 管理虚拟环境
2021/01/21 Python
中东地区为妈妈们提供一切的头号购物目的地:Sprii
2018/05/06 全球购物
Gucci法国官方网站:意大利奢侈品牌
2018/07/25 全球购物
德国黑胶唱片、街头服装及运动鞋网上商店:HHV
2018/08/24 全球购物
优秀公益广告词大全
2014/03/19 职场文书
2014年派出所工作总结
2014/11/21 职场文书
违规违纪检讨书范文
2015/05/06 职场文书
2015中秋节晚会主持词
2015/07/01 职场文书
《富饶的西沙群岛》教学反思
2016/02/16 职场文书
为什么不建议在go项目中使用init()
2021/04/12 Golang