使用es6特性封装async-mysql

时间:2022-10-26 10:46:25

node.js的mysql模块本身没有提供返回promise的函数,即是说都是用的回调函数,那么对于我们使用async函数是很不方便的一件事。node.js有一个mysql封装库叫mysql-promise,这个库提供使用函数拼凑sql语句,但我比较想用原生的sql语句,原因在于mysql对于query函数封装得比较完美,能对应select,delete,update,insert返回不同的结果,比如update和delete返回affectRows,select返回查询结果这样,再加上使用参数化的sql语句能防止sql注入,所以封装了一下mysql的npm包。

首先是package.json,对于Promise,建议使用bluebird.Promise,然后自然是mysql

 {
"name": "async-mysql",
"version": "1.0.0",
"main": "index.js",
"author": {
"name": "kazetotori/fxqn",
"email": "kakkouto98045@live.com"
},
"files": [
"lib",
"index.js"
],
"dependencies": {
"mysql": "2.12.0",
"bluebird": "3.4.6"
}
}

这个库入口文件为index.js,这里仅仅作为一个导出文件使用,没有任何代码

 module.exports.Connection = require('./lib/Connection').Connection;
module.exports.Pool = require('./lib/Pool').Pool;

首先来实现一下单个连接的各个函数,使用es6的class关键字和Symbol封装,比传统的构造函数更加直观

 const mysql = require('mysql');
const bluebird = require('bluebird');
const Promise = bluebird.Promise;
var $originConn = Symbol('originConn');
var $isPoolConn = Symbol('isPoolConn');
var $isAlive = Symbol('isAlive'); /**
* This function is the factory of the standard promise callback.
* @param {Function} resolve
* @param {Function} reject
* @return {Function} The standard promise callback.
*/
function promiseFn(resolve, reject) {
return (err, rst) => {
if (err) reject(err);
else resolve(rst);
}
} /**
* Connection is the class that contains functions that each returns promise.
* These functions are just converted from a Mysql.Connection Object.
*/
class Connection { /**
* Constructor, initialize the connection object.
* @param {Object} config The configuration of the connection.
* @param {Boolean} isPoolConn Orders the connection is in a pool or not.
*/
constructor(config, isPoolConn = false) {
if (config.query)
this[$originConn] = config;
else
this[$originConn] = mysql.createConnection(config);
this[$isPoolConn] = isPoolConn;
this[$isAlive] = true;
} /**
* Connection config
*/
get config() { return this[$originConn].config; } /**
* Orders the connection is in a pool or not.
*/
get isPoolConnection() { return this[$isPoolConn]; } /**
* Orders the connection is destroyed or not.
*/
get isAlive() { return this[$isAlive]; } /**
* Orders the threadId of the connection.
*/
get threadId() { return this[$originConn].threadId; } /**
* Add listener of this connection.
*/
get on() { return this[$originConn].on; }; /**
* Ternimate the connection immediately whether there's any query in quene or not.
*/
destroy() {
return new Promise((resolve, reject) => {
this[$originConn].destroy();
this[$isAlive] = false;
resolve();
});
} /**
* Ternimate the connection. This function will ternimate the connection after any query being complete.
*/
end() {
return new Promise((resolve, reject) => {
this[$originConn].end(promiseFn(resolve, reject))
})
.then(() => {
this[$isAlive] = false;
})
} /**
* Execute sql command with parameters.
* @param {String} cmd The sql command would be executed.
* @param {Array} params Parameters.
* @return {Promise<any>} The sql result.
*/
query(cmd, params) {
return new Promise((resolve, reject) => {
let conn = this[$originConn];
let args = [cmd];
let callback = promiseFn(resolve, reject);
if (params)
args.push(params);
args.push(callback);
conn.query(...args);
});
} /**
* Begin transaction of the connection. Following queries would not be useful until the function commit or rollback called.
* @return {Promise<undefined>}
*/
beginTran() {
return new Promise((resolve, reject) => {
let conn = this[$originConn];
conn.beginTransaction(promiseFn(resolve, reject));
});
} /**
* Commit a transaction.
* @return {Promise<undefined>}
*/
commit() {
return new Promise((resolve, reject) => {
let conn = this[$originConn];
conn.commit((err) => {
if (err) this.rollback().then(() => reject(err));
else resolve();
})
});
} /**
* Rollback a transaction
* @return {Promise<undefined>}
*/
rollback() {
return new Promise((resolve, reject) => {
let conn = this[$originConn];
conn.rollback(() => resolve());
});
}
} /**
* PoolConnection is the class extending from Connection.
* Any object of this class is the connection in a connection pool.
*/
class PoolConnection extends Connection {
constructor(originConn) {
super(originConn, true);
} /**
* Release the connection and put it back to the pool.
* @return {Promise<undefined>}
*/
release() {
return new Promise((resolve, reject) => {
this[$originConn].release();
resolve();
});
}
} module.exports.Connection = Connection;
module.exports.PoolConnection = PoolConnection;

然后是连接池的部分

const Promise = require('bluebird').Promise;
const mysql = require('mysql');
const PoolConnection = require('./Connection').PoolConnection;
var $originPool = Symbol('originPool');
var $isAlive = Symbol('isAlive'); /**
* Pool is the class that contains functions each returns promise.
* These functions are just converted from the Mysql.Pool object.
*/
class Pool { /**
* Constructor, initialize the pool.
* @param {Object} config The pool config.
*/
constructor(config) {
this[$originPool] = mysql.createPool(config);
this[$isAlive] = true;
} /**
* Orders the pool config.
*/
get config() { return this[$originPool].config; } /**
* Orders the pool is destroyed or not.
*/
get isAlive() { return this[$isAlive]; } /**
* Add listener to the pool.
*/
get on() { return this[$originPool].on; } /**
* Get a connection object from the pool.
* @return {Promise<PoolConnection>}
*/
getConn() {
return new Promise((resolve, reject) => {
this[$originPool].getConnection((err, originConn) => {
if (err)
return reject(err);
let conn = new PoolConnection(originConn);
resolve(conn);
});
});
} /**
* Ternimate the pool. This function would ternimate the pool after any query being complete.
*/
end() {
return new Promise((resolve, reject) => {
this[$originPool].end((err) => {
if (err)
return reject(err);
this[$isAlive] = false;
resolve();
})
});
} /**
* Use a connection to query a sql command with parameters.
* @param {String} cmd The sql command would be executed.
* @param {Array} params Parameters.
* @return {Promise<any>}
*/
query(cmd, params) {
return new Promise((resolve, reject) => {
let args = [cmd];
let callback = (err, rst) => {
if (err) reject(err);
else resolve(rst);
}
if (params)
args.push(params);
args.push(callback);
this[$originPool].query(...args);
});
}
} module.exports.Pool = Pool;

最后加一个config,便于智能提示

var $host = Symbol('host');
var $port = Symbol('port');
var $localAddr = Symbol('localAddr');
var $socketPath = Symbol('socketPath');
var $user = Symbol('user');
var $pwd = Symbol('pwd');
var $db = Symbol('db');
var $charset = Symbol('charset');
var $timezone = Symbol('timezone');
var $connTimeout = Symbol('connTimeout');
var $stringifyObjs = Symbol('stringifyObjs');
var $typeCast = Symbol('typeCast');
var $queryFormat = Symbol('queryFormat');
var $supportBigNumbers = Symbol('supportBigNumbers');
var $bigNumberStrings = Symbol('bigNumberStrings');
var $dateStrings = Symbol('dateStrings');
var $debug = Symbol('debug');
var $trace = Symbol('trace');
var $multiStmts = Symbol('multipleStatements');
var $flags = Symbol('flags');
var $ssl = Symbol('ssl'); class MysqlConfig {
constructor(config) {
for (let k in config)
this[k] = config[k];
} get host() { return this[$host] }
set host(val) { this[$host] = val } get port() { return this[$port] }
set port(val) { this[$port] = val } get localAddress() { return this[$localAddr] }
set localAddress(val) { this[$localAddr] = val } get socketPath() { return this[$socketPath] }
set socketPath(val) { this[$socketPath] = val } get user() { return this[$user] }
set user(val) { this[$user] = val } get password() { return this[$pwd] }
set password(val) { this[$pwd] = val } get database() { return this[$db] }
set database(val) { this[$db] = val } get charset() { return this[$charset] }
set charset(val) { this[$charset] = val } get timezone() { return this[$timezone] }
set timezone(val) { this[$timezone] = val } get connectTimeout() { return this[$connTimeout] }
set connectTimeout(val) { this[$connTimeout] = val } get stringifyObjects() { return this[$stringifyObjs] }
set stringifyObjects(val) { this[$stringifyObjs] = val } get typeCast() { return this[$typeCast] }
set typeCast() { this[$typeCast] = val } get queryFormat() { return this[$queryFormat] }
set queryFormat(val) { this[$queryFormat] = val } get supportBigNumbers() { return this[$supportBigNumbers] }
set supportBigNumbers(val) { this[$supportBigNumbers] = val } get bigNumberStrings() { return this[$bigNumberStrings] }
set bigNumberStrings(val) { this[$bigNumberStrings] = val } get dateStrings() { return this[$dateStrings] }
set dateStrings(val) { this[$dateStrings] = val } get debug() { return this[$debug] }
set debug(val) { this[$debug] = val } get trace() { return this[$trace] }
set trace(val) { this[$trace] = val } get multipleStatements() { return this[$multiStmts] }
set multipleStatements(val) { this[$multiStmts] = val } get flags() { return this[$flags] }
set flags(val) { this[$flags] = val } get ssl() { return this[$ssl] }
set ssl(val) { this[$ssl] = val }
} module.exports.MysqlConfig = MysqlConfig;

测试代码

//Use this test.js need node version is higher than 7.0.0 .
//And need the node arg "--harmony". const config = {
"host": "localhost",
"port": 3306,
"user": "root",
"database": "testDB",
"charset": "UTF8_GENERAL_CI",
"timezone": "local",
"connectTimeout": 10000,
"connectionLimit": 10
};
const Pool = require('./lib/Pool').Pool;
const Connection = require('./lib/Connection').Connection;
var pool = new Pool(config);
var conn = new Connection(config); async function poolTest() { //pool.query()
let result = await pool.query('SELECT * FROM tbltest WHERE name=?', ['wr']);
console.log(result); //pool.getConn();
let poolConn = await pool.getConn();
console.log(poolConn.isPoolConnection);
result = await poolConn.query('SELECT * FROM tbltest WHERE name=?', ['zs']);
console.log(result); await pool.end();
console.log(pool.isAlive);
} async function connTest() {
let rst = await conn.query('SELECT * FROM tbltest WHERE name=?', ['ls']);
console.log(rst);
await conn.beginTran();
let count = (await conn.query('SELECT COUNT(*) FROM tbltest WHERE name=?', ['??']))[0]['COUNT(*)'];
console.log(count);
await conn.query('INSERT INTO tbltest(name) VALUES(?)', ['zhangsan']);
if (count > 0) {
await conn.commit();
console.log('commit');
}
else {
await conn.rollback();
console.log('rollback');
} rst = await conn.query('SELECT * FROM tbltest');
console.log(rst);
} poolTest();
connTest();

使用es6特性封装async-mysql的更多相关文章

  1. 9个常用ES6特性归纳&lpar;一般用这些就够了&rpar;

    ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了.它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应 ...

  2. 最常用的ES6特性&lpar;转&rpar;

    最常用的ES6特性 let, const, class, extends, super, arrow functions, template string, destructuring, defaul ...

  3. 最常用的ES6特性

    遇到了要写出es6新特性的题目,所以查阅了资料来总结一下,点击查看原文. 进入正题,最常用的ES6特性有:let, const, class, extends, super, arrow functi ...

  4. ES6特性

    一.ES6特性: let, const, class, extends, super, arrow functions, template string, destructuring, default ...

  5. &lbrack;&period;net 面向对象编程基础&rsqb; &lpar;11&rpar; 面向对象三大特性——封装

    [.net 面向对象编程基础] (11) 面向对象三大特性——封装 我们的课题是面向对象编程,前面主要介绍了面向对象的基础知识,而从这里开始才是面向对象的核心部分,即 面向对象的三大特性:封装.继承. ...

  6. 第四节:教你如何快速让浏览器兼容ES6特性

    写在正文前,本来这一节的内容应该放在第二节更合适,因为当时就有同学问ES6的兼容性如何,如何在浏览器兼容ES6的特性,这节前端君会介绍一个抱砖引玉的操作案例. 为什么ES6会有兼容性问题? 由于广大用 ...

  7. 解决浏览器兼容ES6特性

    为什么ES6会有兼容性问题? 由于广大用户使用的浏览器版本在发布的时候也许早于ES6的定稿和发布,而到了今天,我们在编程中如果使用了ES6的新特性,浏览器若没有更新版本,或者新版本中没有对ES6的特性 ...

  8. C&plus;&plus;三大特性 封装 继承 多态

    C++ 三大特性 封装,继承,多态 封装 定义:封装就是将抽象得到的数据和行为相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成类,其中数据和函数都是类的成员,目的在于将对 ...

  9. 现在就可以使用的5个 ES6 特性

    小编推荐:掘金是一个高质量的技术社区,从 ECMAScript 6 到 Vue.js,性能优化到开源类库,让你不错过前端开发的每一个技术干货.各大应用市场搜索「掘金」即可下载APP,技术干货尽在掌握. ...

随机推荐

  1. java抽象类和接口的区别

    抽象类特点:1.抽象类中可以构造方法2.抽象类中可以存在普通属性,方法,静态属性和方法.3.抽象类中可以存在抽象方法.4.如果一个类中有一个抽象方法,那么当前类一定是抽象类:抽象类中不一定有抽象方法. ...

  2. Gradle 笔记

    网上有一篇文章说的很明白,图文来教你在eclipse下用gradle 来打包Androidhttp://blog.csdn.net/x605940745/article/details/4124268 ...

  3. 小学生之Java中迭代器实现的原理

    一. 引言 迭代这个名词对于熟悉Java的人来说绝对不陌生.我们常常使用JDK提供的迭代接口进行java collection的遍历: Iterator it = list.iterator();wh ...

  4. Verilog中的标点

    在Verilog中有时候会误用的上引号 1,define 中的 `define INITIAL  0 这个单引号用的是键盘左上角的那个单引号,其实就是一个小撇. 2,4'd0 这个 用的是才是叫真正的 ...

  5. 喜马拉雅音频下载工具 - xmlyfetcher

    xmlyfetcher用于下载喜马拉雅歌曲资源,可以下载单个音频资源,也可以下载整个专辑. 项目地址:https://github.com/smallmuou/xmlyfetcher 安装 安装jsh ...

  6. 使用spark ml pipeline进行机器学习

    一.关于spark ml pipeline与机器学习 一个典型的机器学习构建包含若干个过程 1.源数据ETL 2.数据预处理 3.特征选取 4.模型训练与验证 以上四个步骤可以抽象为一个包括多个步骤的 ...

  7. 【Android Studio安装部署系列】十、Android studio打包发布apk安装包

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 使用Android studio发布apk安装包的操作步骤. 开始打包发布apk Build > Generate Signe ...

  8. crontab每隔1天执行【转】

    有个需求,crontab任务需要每隔1天执行,有俩个方法,如下: 第一种方法,利用crontab执行 */ * * shellscript 但是这种方法有个问题,就是有个月份有31天,导致本月31号和 ...

  9. 在Winform开发中使用FastReport创建报表

    FastReport.Net是一款适用于Windows Forms, ASP.NET和MVC框架的功能齐全的报表分析解决方案.可用在Microsoft Visual Studio 2005到2015, ...

  10. 【nodejs】让nodejs像后端mvc框架(asp&period;net mvc)一样处理请求--控制器和处理函数的注册篇(4&sol;8)【controller&plus;action】

    文章目录 前情概要 前边的文章把一些基本的前置任务都完成了.接下就是比较重要的处理函数action是如何自动发现和注册的拉,也就是入口函数RouteHandler(也是我们的第一个express中间件 ...