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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Node.js 环境里面访问 MySQL 的默认方式,采用了古老的回调方式,这样很容易产生回调地狱。那么如何避免呢?这里介绍一种基于 Promise 的封装方式,可以避免回调地狱,并且支持事务访问。

select 获取 model

同上,拼接 select


分页和查询

使用limit来分页。其他分页方式待定。

/**
* 分页获取数据,可以查询
* @param { MySQLHelp } help 访问数据库的实例
* @param { Object } info 表、字段
* @param { Object } query 查询条件
* @param { Object } pager 数据
* @returns 添加记录的ID
* * info 结构:
* * * tableName:'', 表名
* * * cols:{colName: '类型'}, 需要显示的字段
* * query 结构(查询条件):
* * * { colName: [401, 11] } 字段名称,查询方式,查询关键字
* * pager 结构:
* * * pageSize: 20 // 一页显示多少条记录
* * * orderBy: { id: false } // 排序字段:字段名,false表示倒序。
* * * pageTotal: 100 // 符合查询条件的总记录数 
* * * pageIndex: 1 // 显示第几页的记录,从 1 开始
*/
asyncfunction getPager(help, info, query, pager) {
console.log('开始分页 :')
const myPromise = newPromise((resolve, reject) => {
// 查询条件和查询参数
const { whereQuery, whereValue } = help._getWhereQuery(query)
// 设置排序和分页
const { orderBy, limit } = help._getPager(pager)
// 设置显示的字段
const showCol = Object.keys(info.cols)
if (showCol.length === 0 ) {showCol.push('*')}
// 拼接查询语句
const sql = `SELECT ${showCol.join(',')} FROM ${info.tableName} ${whereQuery} ${orderBy} ${limit}`
console.log('select-sql:', sql, whereValue)
help.query(sql, whereValue)
.then((res) => {
// 添加成功
resolve(res)
})
.catch((err) => {
// 出错了
console.log('分页获取记录失败了:', err)
reject(err)
})
})
return myPromise
}
function getCount(help, info, query) {
returnnewPromise((resolve, reject) => {
// 查询条件和查询参数
const { whereQuery, whereValue } = help._getWhereQuery(query)
// 统计总数
const sql = `SELECT count(1) as count FROM ${info.tableName} ${whereQuery} `
console.log('count-sql:', sql, whereValue)
help.query(sql, whereValue).then((re) => {
resolve(re[0].count)
}).catch((err) => {
// 出错了
console.log('统计总记录数失败了:', err)
reject(err)
})
})
}
module.exports = {
getCount,
getPager
}


其他待定

以上仅仅是基础的增删改查的封装,SQL非常灵活,还有 group by、 级联查询、子查询等各种形式,这些以后再说。

因为每个功能都做成了单独的js文件,这样就可以遵守“对扩展开放对修改关闭”的开闭原则。

就是说,可以很方便的做扩展。


使用方式和测试


封装完毕,那么要如何使用呢?

37.png


MySQL使用与测试.png

使用和测试分为三个维度:是否使用事务、单条还是多条、是否await

  1. 单条操作,无事务;
  • 添加、修改、删除获取的基础操作。
  • 分页、查询等基础操作。
  1. 多条操作,有事务;
  • 批量添加
  • 主从添加
  • 模拟转账
  • 添加、修改、删除
  • 回滚测试
  1. 事务的开启方式
  • Promise 模式
  • await 模式
  • 多事务同时开始,测试干扰性

由于篇幅有限,这里先介绍基础使用方式。


基本使用方式


基于 model 的添加、修改、删除和获取 这里说的 model 是基于业务需求建立的,而不是基于表建立的。

首先引入封装的函数以及配置信息,建立实例:

// 引入help
const {
MySQLHelp,
addModel,
updateModel,
deleteModel,
getModel
} = require('../packages/mysql.js')
// 配置信息
const config = require('../public/config/mysql-test.json')
// 实例
const help = new MySQLHelp(config)


然后建立实现添加、修改、删除和获取的函数:

// meta
const meta = require('../public/model/10010-user.json')
let newDataId = 0
// 添加数据的测试
const test_addData = (number) => {
console.log('\n---- addModel ----')
returnnewPromise((resolve, reject) => {
// 要添加的数据
const model = {
name: '测试基础添加数据-A-11',
age: number
}
// meta.tableName = 'a'
addModel(help, meta, model).then((newId) => {
// 添加成功
console.log('外部添加新数据:', newId)
newDataId = newId
resolve()
})
})
}
// 修改数据的测试
const test_updateData = () => {
console.log('\n---- updateModel ----')
returnnewPromise((resolve, reject) => {
// 要修改的数据
const model = {
name: '测试基础添加数据-A-11--修改了',
age: 300
}
// meta.tableName = 'a'
updateModel(help, meta, model, newDataId).then((count) => {
// 添加成功
console.log('修改数据,影响行数:', count)
resolve()
})
})
}
// 删除数据的测试
const test_deleteData = () => {
console.log('\n---- deleteModel ----')
returnnewPromise((resolve, reject) => {
// meta.tableName = 'a'
deleteModel(help, meta, newDataId).then((count) => {
// 添加成功
console.log('删除数据,影响行数:', count)
resolve()
})
})
}
// 获取数据的测试
const test_getData = () => {
console.log('\n---- updateModel ----')
returnnewPromise((resolve, reject) => {
// meta.tableName = 'a'
getModel(help, meta, newDataId).then((model) => {
// 添加成功
console.log('获取model:', model)
resolve(model)
})
})
}


  • addModel
    传入需要的参数,然后可以得到新添加的记录的主键ID。


依次执行的测试


test_addData('51').then(() => {
// 修改
return test_updateData()
}).then(() => {
// 获取
return test_getData()
}).then(() => {
// 删除
return test_deleteData()
}).then(() => {
help.close()
})


执行结果:

38.png运行结果


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6天前
|
关系型数据库 MySQL 数据库连接
解决 mysql8.0 ERROR 1045 (28000): Access denied for user ‘ODBC‘@‘localhost‘ (using password: NO)用户访问拒绝
解决 mysql8.0 ERROR 1045 (28000): Access denied for user ‘ODBC‘@‘localhost‘ (using password: NO)用户访问拒绝
194 52
解决 mysql8.0 ERROR 1045 (28000): Access denied for user ‘ODBC‘@‘localhost‘ (using password: NO)用户访问拒绝
|
6天前
|
运维 监控 关系型数据库
Serverless 应用引擎产品使用之在阿里云函数计算(FC)中,要访问另一个账号的rds配置rds的白名单如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
53 0
|
6天前
|
JavaScript 前端开发 关系型数据库
node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染
node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染
32 1
|
6天前
|
JavaScript 前端开发 API
node+vue3+mysql前后分离开发范式——实现对数据库表的增删改查
node+vue3+mysql前后分离开发范式——实现对数据库表的增删改查
38 1
|
6天前
|
安全 关系型数据库 MySQL
node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)
node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)
28 3
|
6天前
|
安全 关系型数据库 Linux
centos7_安装mysql8(局域网访问navicat连接)
centos7_安装mysql8(局域网访问navicat连接)
33 1
|
6天前
|
SQL 关系型数据库 MySQL
mysql查询语句的访问方法const、ref、ref_or_null、range、index、all
mysql查询语句的访问方法const、ref、ref_or_null、range、index、all
|
6天前
|
关系型数据库 MySQL Docker
Docker从容器中项目如何访问到宿主机MYSQL
Docker从容器中项目如何访问到宿主机MYSQL
191 0
|
6天前
|
关系型数据库 MySQL 数据库
docker容器访问宿主机mysql数据库
docker容器访问宿主机mysql数据库
91 0
|
6天前
|
资源调度 JavaScript 关系型数据库
Node.js【文件系统模块、路径模块 、连接 MySQL、nodemon、操作 MySQL】(三)-全面详解(学习总结---从入门到深化)
Node.js【文件系统模块、路径模块 、连接 MySQL、nodemon、操作 MySQL】(三)-全面详解(学习总结---从入门到深化)
37 0