Koa 数据库连接和查询分离, CommonJS 模块遇到的一个坑
踩坑小结一下, 在使用 koa + mysql 进行数据库查询时。为了不让 连接数据库 和 查询数据库 以及路由都在一个文件中(臃肿),特分离三个文件。分别处理 mysql连接、mysql异步查询、处理路由请求等。
结构如下:
- index.js
- mysql_config.js
- async_db.js
index.js 代码如下:
const Koa = require("koa");
const Router = require("@koa/router");
const { connect_mysql } = require("./mysql_config");
const { findSession } = require("./async_db");
const app = new Koa();
const router = new Router().prefix("/api");
// 连接数据库
connect_mysql();
router.get("/session", async ctx => {
try {
const { results } = await findSession("SELECT * FROM _mysql_session_store");
ctx.body = {
errno: 0,
data: results
};
} catch (e) {
ctx.status = 500;
ctx.body = e;
}
});
app.use(router.routes(), router.allowedMethods());
app.listen(3001);
mysql_config.js 代码如下:
const mysql = require("mysql");
let connection;
const connect_mysql = () => {
connection = mysql.createConnection({
host: "127.0.0.1",
user: "root",
password: "abc123",
database: "base"
});
};
module.exports = {
connection,
connect_mysql
};
async_db.js 代码如下
const { connection } = require("./mysql_config");
const findSession = sql => {
return new Promise((resolve, reject) => {
connection.query(sql, (err, results, fileds) => {
if (err) return reject(err);
resolve({
results,
fileds
});
});
});
};
module.exports = {
findSession
};
结果在浏览器访问 http://localhost:3001/api/session
时, 查询的结果是 {}。
一番排查后, 发现在 async_db.js 引入的 connection 对象为 undefined。但是在 index.js 文件, 开启服务器的时候已经和服务器建立连接, 并且将结果赋值给 connection 变量了, 在别的文件取不到值呢?
原来在 async_db.js 文件中访问的 connection 是最开始值的拷贝,在mysql_config.js导出的时候并没有对 connection初始化, 就算后面完成了赋值, 但是在别的模块中也任然只能访问最开始的一份拷贝值 undefined。
解决
修改 mysql_config.js 文件, 创建一个闭包环境, 将 connection 保存在闭包中, 并对外提供一个可以随时访问闭包环境中的 connection 值。
const mysql = require("mysql");
(function() {
// 创建数据库会话
let connection;
const connect_mysql = () => {
connection = mysql.createConnection({
host: "127.0.0.1",
user: "root",
password: "abc123",
database: "base"
});
};
const getConnection = () => connection;
module.exports = { getConnection, connect_mysql };
})();
在 async_db.js 中引入 getConnection 函数来获取已初始化好的 connection值。
const { getConnection } = require("./mysql_config");
const findSession = sql => {
return new Promise((resolve, reject) => {
getConnection().query(sql, (err, results, fileds) => {
if (err) return reject(err);
resolve({
results,
fileds
});
});
});
};
module.exports = {
findSession
};