详解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 相关文章推荐
在第一个input框内输入内容.textarea自动得到第一个文件框的值的javascript代码
Apr 20 Javascript
jquery中页面Ajax方法$.load的功能使用介绍
Oct 20 Javascript
JavaScript获取表单enctype属性的方法
Apr 02 Javascript
基于jQuery插件实现环形图标菜单旋转切换特效
May 15 Javascript
详解javascript实现瀑布流绝对式布局
Jan 29 Javascript
JavaScript事件处理的方式(三种)
Apr 26 Javascript
js常用DOM方法详解
Feb 04 Javascript
JavaScript实现修改伪类样式
Nov 27 Javascript
Jquery遍历筛选数组的几种方法和遍历解析json对象,Map()方法详解以及数组中查询某值是否存在
Jan 18 jQuery
JS实现放烟花效果
Mar 10 Javascript
js 动态校验开始结束时间的实现代码
May 25 Javascript
Vue组件生命周期运行原理解析
Nov 25 Vue.js
轻松掌握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
Laravel5中Cookie的使用详解
2017/05/03 PHP
用Laravel Sms实现laravel短信验证码的发送的实现
2018/11/29 PHP
Get中文乱码IE浏览器Get中文乱码解决方案
2013/12/26 Javascript
javascript常见操作汇总
2014/09/03 Javascript
JS简单实现城市二级联动选择插件的方法
2015/08/19 Javascript
使用bootstrap validator的remote验证代码经验分享(推荐)
2016/09/21 Javascript
Vue.js进行查询操作的实例详解
2017/08/25 Javascript
Vue多组件仓库开发与发布详解
2019/02/28 Javascript
js获取本日、本周、本月的时间代码
2020/02/01 Javascript
小程序使用分包的示例代码
2020/03/23 Javascript
vue实现图书管理系统
2020/12/29 Vue.js
[03:10]2014DOTA2 TI马来劲旅Titan首战告捷目标只是8强
2014/07/10 DOTA
Python日志模块logging简介
2015/04/13 Python
浅析Python编写函数装饰器
2016/03/18 Python
Python heapq使用详解及实例代码
2017/01/25 Python
django数据关系一对多、多对多模型、自关联的建立
2019/07/24 Python
pytorch自定义初始化权重的方法
2019/08/17 Python
python剪切视频与合并视频的实现
2020/03/03 Python
Python标准库shutil模块使用方法解析
2020/03/10 Python
基于python SMTP实现自动发送邮件教程解析
2020/06/02 Python
keras 多任务多loss实例
2020/06/22 Python
Maje德国官网:法国女性成衣品牌
2017/02/10 全球购物
Book Depository欧盟:一家领先的国际图书零售商
2019/05/21 全球购物
欧姆龙医疗欧洲有限公司:Omron Healthcare Europe B.V
2020/06/13 全球购物
举例说明类变量和实例变量的区别
2016/06/30 面试题
高中的职业生涯规划书
2013/12/28 职场文书
大学生自我评价范文分享
2014/02/21 职场文书
高考备战决心书
2014/03/11 职场文书
医学检验专业自荐信
2014/09/18 职场文书
学校党委副书记个人对照检查材料思想汇报
2014/09/28 职场文书
区长工作作风个人整改措施
2014/10/01 职场文书
2015年幼儿园卫生保健工作总结
2015/05/12 职场文书
股东协议书范本2016
2016/03/21 职场文书
golang 实现并发求和
2021/05/08 Golang
使用Pytorch实现two-head(多输出)模型的操作
2021/05/28 Python
Java实现简易的分词器功能
2021/06/15 Java/Android