详解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 相关文章推荐
在一个浏览器里呈现所有浏览器测试结果的前端测试工具的思路
Mar 02 Javascript
面向对象设计模式的核心法则
Nov 10 Javascript
jQuery实现的支持IE的html滑动条
Mar 16 Javascript
javascript中eval函数用法分析
Apr 25 Javascript
js实现登陆遮罩效果的方法
Jul 28 Javascript
bootstrap datepicker限定可选时间范围实现方法
Sep 28 Javascript
支持移动端原生js轮播图
Feb 16 Javascript
前端页面文件拖拽上传模块js代码示例
May 19 Javascript
浅谈vue的props,data,computed变化对组件更新的影响
Jan 16 Javascript
JSON生成Form表单的方法示例
Nov 21 Javascript
Javascript模块化机制实现原理详解
Apr 02 Javascript
基于Vue sessionStorage实现保留搜索框搜索内容
Jun 01 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自定义错误用法示例
2016/09/28 PHP
Yii2中添加全局函数的方法分析
2017/05/04 PHP
PHP实现QQ、微信和支付宝三合一收款码实例代码
2018/02/19 PHP
清华大学出版的事半功倍系列 javascript全部源代码
2007/05/04 Javascript
javascript addBookmark 加入收藏 多浏览器兼容
2009/08/15 Javascript
基于jquery实现导航菜单高亮显示(两种方法)
2015/08/23 Javascript
javascript字符串函数汇总
2015/12/06 Javascript
JS文件上传神器bootstrap fileinput详解
2021/01/28 Javascript
JS常用加密编码与算法实例总结
2016/12/22 Javascript
Javascript实现从小到大的数组转换成二叉搜索树
2017/06/13 Javascript
Angular开发实践之服务端渲染
2018/03/29 Javascript
JS实现图片拖拽交换效果
2018/11/30 Javascript
使用nvm和nrm优化node.js工作流的方法
2019/01/17 Javascript
js+canvas实现两张图片合并成一张图片的方法
2019/11/01 Javascript
解决Vue在Tomcat8下部署页面不加载的问题
2019/11/12 Javascript
解决vue+webpack项目接口跨域出现的问题
2020/08/10 Javascript
对于Python的框架中一些会话程序的管理
2015/04/20 Python
浅析python协程相关概念
2018/01/20 Python
对Python 数组的切片操作详解
2018/07/02 Python
利用Python如何实现一个小说网站雏形
2018/11/23 Python
简单了解python高阶函数map/reduce
2019/06/28 Python
Django REST Framework序列化外键获取外键的值方法
2019/07/26 Python
python3 tcp的粘包现象和解决办法解析
2019/12/09 Python
django rest framework serializers序列化实例
2020/05/13 Python
Python面向对象多态实现原理及代码实例
2020/09/16 Python
用纯css3和html制作泡沫对话框实现代码
2013/03/21 HTML / CSS
HTML5打开手机扫码功能及优缺点
2017/11/27 HTML / CSS
英国品牌男装折扣网站:Brown Bag
2018/03/08 全球购物
Redbubble法国:由独立艺术家设计的独特产品
2019/01/08 全球购物
C#如何允许一个类被继承但是避免这个类的方法被重载?
2015/02/24 面试题
幼儿园教学随笔感言
2014/02/23 职场文书
企业法人代表授权委托书
2014/10/02 职场文书
教师批评与自我批评(群众路线)
2014/10/15 职场文书
技术入股协议书
2016/03/22 职场文书
使用jpa之动态插入与修改(重写save)
2021/11/23 Java/Android
提高系统的吞吐量解决数据库重复写入问题
2022/04/23 MySQL