告别回调地狱,在Node里优雅的访问MySQL(一)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: Node.js 环境里面访问 MySQL 的默认方式,采用了古老的回调方式,这样很容易产生回调地狱。那么如何避免呢?这里介绍一种基于 Promise 的封装方式,可以避免回调地狱,并且支持事务访问。


技术栈


  • Node.js  V14.16.0
  • MySQL V 8.0.15
  • ES6
  • 基于对象

思路和结构


36.png

MySQL.help


实现基础访问


建立一个help,实现基础功能。

/**
* 基于 promise 封装 MySQL 的基本操作,支持事务
* * 创建数据库连接
* * 事务相关
* * 提交SQL给数据库执行,得到返回结果
* * 共用函数
*/
class MySQLHelp {
constructor (info) {
// 创建普通连接的参数
this._info = {
host: 'localhost',
port: '3306',
user: 'root',
password: '',
database: ''
}
// 创建池子的参数
this._infoTran = {
host: 'localhost',
port: '3306',
user: 'root',
password: '',
database: '',
connectionLimit: 20
}
// 加参数
Object.assign(this._info, info)
Object.assign(this._infoTran, info)
// 预定一个池子,用于事务
this.pool = null
console.log(' ★ 初始化:不使用事务!')
// 不使用事务,开启连接获得数据库对象,其实也支持事务
this.db = mysql.createConnection(this._info)
//启动连接
this.db.connect((err) => {
if(err) {
console.error('连接数据发生错误:', err)
} else {
console.log('★ [MySQL 已经打开数据库,threadId:]', this.db.threadId)
}
})
}


非事务模式

默认不使用事务,内部创建一个链接数据库的对象,用于实现各种操作。好吧,其实只有一个操作,提交SQL到数据库,然后等待返回结果。

其实我试了一下,这个默认的连接对象,也可以使用事务,只是看到网上提到事务,都是用 pool 的方式。所以事务用的连接对象也采用从 pool 里面获取,因为对比了一下两种连接对象,确实不太一样。


提交SQL给MySQL执行

/**
* 把 SQL 提交给数据库。支持事务。
* @param { string } sql sql语句
* @param { array } params 需要的参数,数组形式
* @param { connection } cn 如果使用事务的话,需要传递一个链接对象进来
* @returns Promise 形式
*/
query(sql, params=[], cn = this.db) {
const myPromise = newPromise((resolve, reject) => {
// 把SQL语句提交给数据库执行,然后等待回调
cn.query(sql, params, (err, res, fields) => {
if (err) { //失败
// 如果开始事务,自动回滚
if (cn !== this.db) {
cn.rollback((err) => {
console.log('执行SQL失败,数据回滚:', err)
})
}
reject(err)
return
}
resolve(res)
})
})
return myPromise
}


  • sql
    要执行的SQL语句,建议参数化的SQL。
  • params
    SQL语句的参数,强烈建议采用参数化的方式,因为可以避免SQL注入攻击。
  • cn
    连接对象,如果不用事务,则使用默认的内部连接对象;如果使用事务,则需要传递一个链接对象进来,以便于区分不同的事务操作。
  • 异常默认回滚
    如果出错,在开启事务的情况下,默认回滚事务。

MySQL的基础操作非常简单,就这一个。其他的就是事务如何开启、提交,SQL如何管理的问题。下面来一一介绍。


实现事务


建立池子,获取连接对象,然后把这个连接对象作为参数,这样就可以非常灵活的实现各种各样的操作了。


建立连接池,获取连接对象

建立连接池不是回调函数,但是从中获取连接对象却是一个回调函数,所以只好封装一个内部函数,便于后续操作。


/**
* 在池子里面获取一个链接,创建对象
*/
_poolCreateConnection() {
const myPromise = newPromise((resolve, reject) => {
console.log('初始化:使用事务')
// 如果没有池子则创建一个。好在不是异步
if (this.pool === null) {
this.pool = mysql.createPool(this._infoTran)
}
// 从池子里面获取一个链接对象,这个是异步
this.pool.getConnection((err, connection) => {
if(err) {
reject(err)
} else {
resolve(connection)
}
})
})
return myPromise
}


开启事务

因为开启事务又是一个异步操作,所以只好继续写个内部函数,实现开始事务的功能,然后再做一个对外的函数实现事务操作。


内部事务函数

/**
* 内部开启事务
*/
_beginStran(_cn) {
const myPromise = newPromise((resolve, reject) => {
_cn.beginTransaction((err) => {
if (err) { //失败
console.log('[★ ★ MySQL 开启事务时报错:] --- ', err)
reject(err)
return
}
console.log('[★ MySQL 事务已经开启:] - ')
resolve(_cn)
})
})
return myPromise
}


对外的事务函数:


/**
* 开启一个事务,Promise 的方式
*/
begin() {
const myPromise = newPromise((resolve, reject) => {
console.log('★ 开启事务,promise 模式')
this._poolCreateConnection().then((_cn) => {
// 开启事务
this._beginStran(_cn)
.then(() => {resolve(_cn)}) // 返回连接对象
.catch((err) => {reject(err)})
})
})
return myPromise
}


其实一个有三个函数,两个内部函数一个对外的函数。这么做是为了代码可以更简洁一些,看起来好看一点,否则各种回调地狱,保证你想哭。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
关系型数据库 MySQL Linux
Docker安装Mysql5.7,解决无法访问DockerHub问题
当 Docker Hub 无法访问时,可以通过配置国内镜像加速来解决应用安装失败和镜像拉取超时的问题。本文介绍了如何在 CentOS 上一键配置国内镜像加速,并成功拉取 MySQL 5.7 镜像。
305 2
Docker安装Mysql5.7,解决无法访问DockerHub问题
|
29天前
|
SQL JavaScript 关系型数据库
node博客小项目:接口开发、连接mysql数据库
【10月更文挑战第14天】node博客小项目:接口开发、连接mysql数据库
|
1月前
|
SQL JavaScript 关系型数据库
Node.js 连接 MySQL
10月更文挑战第9天
20 0
|
2月前
|
SQL JavaScript 关系型数据库
Node服务连接Mysql数据库
本文介绍了如何在Node服务中连接MySQL数据库,并实现心跳包连接机制。
43 0
Node服务连接Mysql数据库
|
3月前
|
JavaScript 关系型数据库 MySQL
node连接mysql,并实现增删改查功能
【8月更文挑战第26天】node连接mysql,并实现增删改查功能
60 3
|
3月前
|
JavaScript Linux 容器
【Azure 应用服务】NodeJS项目部署在App Service For Linux环境中,部署完成后应用无法访问
【Azure 应用服务】NodeJS项目部署在App Service For Linux环境中,部署完成后应用无法访问
|
3月前
|
JavaScript 前端开发 API
揭秘Node.js如何轻松访问API:一个示例足以改变你的开发视角!
【8月更文挑战第21天】在现代Web开发中,API是软件间通信的关键。Node.js以其高效性,在API访问上独具优势。本文通过示例展示如何用Node.js访问API。首先确保已安装Node.js,然后使用npm安装`axios`库。创建`api_example.js`文件,并编写代码以访问JSONPlaceholder API获取数据。成功时,响应数据会输出至控制台;若失败,则打印错误。此示例展示了Node.js结合`axios`访问API的便捷性及高效性,为初学者提供快速入门指南。
36 0
|
11天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
26 1
|
13天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
29 4
|
20天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
91 1
下一篇
无影云桌面