一、Node操作Mysql
1.1 介绍和意义
1.2 操作流程
1.2.1 下载mysql模块
npm i mysql
1.2.2 在后端js文件中引入mysql
const mysql = require('mysql')
1.2.3 先创建mysql数据库的配置连接
let connectObj = mysql.createConnection({ host:'主机名', user:'用户名', password:'密码' port:'端口号', database:'要操作哪个数据库' })
1.2.4 使用connectObj.query
使用query方法执行sql语句
connectObj.query(sqlStr,(err,results)=>{ })
nodejs通过msyql包操作mysql数据库的步骤【重点】:
第一步:引入mysql包
第二步:创建mysql连接:mysql.createConnection();
第三步:开始连接mysql: mysqlObj.connect();
第四步:执行sql语句:mysqlObj.query('sql语句'[,参数值],回调方法);
nodejs通过msyql包操作mysql数据库的代码实例1:
//第一步:引入mysql包 const mysql = require('mysql'); // console.log(mysql); //第二步:创建mysql连接:mysql.createConnection(); const mysqlObj = mysql.createConnection({ host: 'localhost', port: 3306, user: 'root', password: 'root', database: 'mydemo' }); // console.log(mysqlObj); //第三步:开始连接mysql: mysqlObj.connect(); mysqlObj.connect(); //第四步:执行sql语句:mysqlObj.query('sql语句'[,参数值],回调方法); // let sql = `insert into class(banji,teacher)values('go语言开发','张老师')`; // let sql = `select * from xsb where szx='计算机系'`; // let sql = `select * from xsb where szx=?`; let sql = `insert into class(banji,teacher)values(?,?)`; // let val = '数学系'; // let val = '信息系'; let val = 'web开发3班'; let teachers = '张老师'; mysqlObj.query(sql, [val, teachers], (err, data) => { console.log(err, data); // for (let obj of data) { // console.log(`姓名:${obj.xm} 年龄:${obj.age} 所在系:${obj.szx}`); // } });
nodejs通过msyql包操作mysql数据库的代码实例2:
const express = require('express'); const path = require('path'); const mysql = require('mysql'); const app = express(); app.listen(3000, () => { console.log('3000端口'); }); //第二步:创建mysql连接:mysql.createConnection(); const mysqlObj = mysql.createConnection({ host: 'localhost', port: 3306, user: 'root', password: 'root', database: 'mydemo' }); // console.log(mysqlObj); //第三步:开始连接mysql: mysqlObj.connect(); mysqlObj.connect(); app.use(express.urlencoded({ extended: false })); //设置ejs: app.set('view engine', 'ejs'); //设置模板引擎为ejs app.set('views', [`${path.join(__dirname,'moban')}`]); //设置模板文件的存放位置 app.engine('html', require('ejs').__express); //将html文件作为ejs模板文件来解析 //显示搜索界面: app.get('/', (req, res) => { res.render('find.html'); }); //处理查询学生: app.post('/', (req, res) => { //接参(用户输入的要查询姓名) let { usr = '' } = req.body; if (usr == '') { res.send(`<script>alert('学生姓名不能为空');location.href='/';</script>`); return; } let sql = `select * from xsb where xm like '%${usr}%'`; let str = ''; mysqlObj.query(sql, (err, data) => { for (let obj of data) { str += `<div>姓名:${obj.xm} 年龄:${obj.age}</div>`; } res.send(str); }); });
find.html文件代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="/" method="post"> <input type="text" name="usr" placeholder="请输入要查询的学生姓名"> <button>搜索</button> </form> </body> </html>
二、promise与异步
2.1什么是Promise【重点】
Promise是异步编程的解决方案之一(异步编程中数据传递或回调嵌套的问题),Promise实际上是一个许诺器,它里面通常放的是将来要执行的异步代码,这些代码执行完成后会有两种结果:成功或失败,因此Promise有三种状态:pending(初始状态)、success/fullfill(成功状态)、reject(失败状态),当我们在Promise内部调用了成功时的回调方法resolve()时则把Promise的pending(初始状态)转换成success/fullfill(成功状态),当我们在Promise内部调用了失败时的回调方法reject()时则把Promise的pending(初始状态)转换成reject(失败状态)。
Promise的特点:【重点】
1、Promise内部的代码是以同步方式执行的;
2、通过Promise对象调用多个then()方法,但调用多个catch()没有意义;
3、在then()方法中可以通过return返回具体的值或Promise对象给后面的then()传递参数值;
2.2 什么是同步【重点】
当前调用发出之后在没有得到结果之前后续代码不能执行,后续代码一直处于在线等待状态,同步是阻塞的。
代码演示:(1)使用alert介绍同步阻塞(2)使用函数计算两个数的和调用后用变量接收
2.3 什么是异步【重点】
当前调用发出之后在没有得到结果之前后续代码可以执行,当前调用的结果会以通知、回调函数的方式告诉调用者,异步是非阻塞的。
常见的应用场景:(1)网络请求(2)读取文件(3)js中的事件函数就是非常典型的异步表现形式。
代码演示:使用定时器模拟异步感受异步编程的特点。
2.4 回调函数
2.4.1 简介
在使用JavaScript时,为了实现某些逻辑经常会写出层层嵌套的回调函数,如果嵌套过多,会极大影响代码可读性和逻辑,这种情况被称为回调地狱(或回调)。而往往一些异步操作需要使用回调函数拿到结果
2.4.2 表现形式
2.4.3 优化回调函数
优化前:
fn1( function(买彩票){ fn2( function(中奖){ fn3( function(还房贷){ } ) } ) } )
优化后:
async function(){ const res1 = await 买了彩票 const res2 = await 中了特等奖500万,等待领奖 const res3 = await 去还房贷 }
2.5 promise
2.5.1 promise简介
Promise(许诺) 是异步编程的一种解决方案,就是一个容器,里面保存着某个未来才会结束的事件。
2.5.2 语法:
基本语法:
new Promise( (resolve,reject)=>{ // resolve() // reject() } )
代码案例:
<script> //Promise内部的代码是以同步方式执行的 console.log('111'); new Promise(() => { console.log(222); }); console.log(333); </script>
2.5.3 promise状态
2.5.4 promise对象方法
2.5.4.1 then
注意:Promise对象的then()调用完成后返回的是Promise对象
语法:
promise对象.then( (结果)=>{ //代码块 } ) <script> let prm = new Promise((resolve, reject) => { // if (1) { if (0) { resolve('OK'); //调用成功时的回调函数 } else { reject('出错了'); //调用失败时的回调函数 } }); prm.then(function(d) { console.log(d, 222); }, function(e) { console.log(e, 888); }); //Promise对象的then()调用完成后返回的是Promise对象 console.log(prm.then(), 666); </script>
2.5.4.2 catch
注意:Promise对象的catch()调用完成后返回的是Promise对象
语法:
promise对象.catch( (异常)=>{ //代码块 } )
代码案例:
<script> let prm = new Promise((resolve, reject) => { // if (1) { if (0) { resolve('OK'); //调用成功时的回调函数 } else { reject('出错了'); //调用失败时的回调函数 } }); prm.then(function(d) { console.log(d, 222); }).catch(function(e) { console.log(e, 777); }); </script>
2.5.5 链式调用【重点】
注意:1)、可以通过Promise对象调用多个then()方法,但只需要调用一次catch()方法
2)、在then()方法中可以通过return返回具体的值或Promise对象给后面的then()传递参数值;
代码案例:
<script> let prm2 = new Promise((resolve, reject) => { setTimeout(() => { // if (1) { if (0) { resolve('Helllo'); } else { reject('这是错误信息'); } }, 2000); }); // prm2.then((d) => { // console.log(d, 11); // }).then((d2) => { // console.log(d2, 222); // }).then(d3 => { // console.log(d3, 333); // }).catch(e => { // console.log(e, 999); // }); prm2.then(d => { console.log(d, 111); }).catch(e => { console.log(e, 333); }).catch(e2 => { console.log(e2, 555); }).catch(e3 => { console.log(e3, 666); }); function demo(data) { return new Promise((resolve, reject) => { if (1) { resolve(data); } else { reject('失败了'); } }); } let p = demo('A'); p.then(d => { console.log(d, 111); return demo('B'); // p = demo('B'); // p.then(d2 => { // console.log(d2, 222); // }).catch(e2 => { // console.log(e2); // }); }).then(d2 => { console.log(d2, 222); // return demo('C'); return 'Yes OK'; }).then(d3 => { console.log(d3, 333); }).catch(e => { console.log(e, 9999); }); </script>
2.5.6 Promise.all():并发方法
该方法用于将多个 Promise 实例,包装成一个新的 Promise 实例,也就是说通过all()方法来同时执行多个不同的Promise实例。
Promise.all()方法的特点:
1)、all()方法中的所有Promise实例都执行成功时返回的是一个数组,数组的元素值与all()方法中的Promise实例一一对应;
2)、all()方法中只要有一个Promise实例执行失败则all()方法就执行失败,如果all()方法中的Promise实例都执行失败则返回的值是最先失败的Promise实例的结果;
3)、all()要么都成功,要么都失败;
语法:
Promise.all( [ Promise实例1,Promise实例2,... ] )
代码案例:
<script> function test1() { return new Promise((resolve, reject) => { setTimeout(() => { if (1) { //if (0) { resolve('Hello WEB'); } else { reject('失败了'); } }, 3000); }); } function test2() { return new Promise((resolve, reject) => { setTimeout(() => { if (1) { // if (0) { resolve('Yes OK'); } else { reject('出错。。。'); } }, 2000); }); } // let prm = Promise.all([test1(), test2()]); let prm = Promise.all([test2(), test1()]); // console.log(prm); prm.then(data => { console.log(data, 111); }).catch(err => { console.log(err, 999); }); </script>
三、async函数
ES2017 标准引入了 async 函数,它是一个关键字,被async修饰的函数称为async函数。
作用:async函数是异步编程解决方案之一,它是以同步流程表达异步操作。它是对Promise的一种扩展,让异步更加方便,彻底解决回调嵌套
async函数的特点:【重点】
1)、async的特点:
(1)、async可以单独使用;
(2)、async函数调用完成后返回的是Promise对象;
<script> function demo() { } // console.log(demo()); // undefined async function fn() { } console.log(fn()); //async函数调用后返回的是Promise对象 // fn().then(d => { // console.log(d, 999); // }).catch(e => { // console.log(e); // }) </script>
2)、await的特点:【重点】
(1)、await不能单独使用,必须与async一起使用;
(2)、await通常等待的Promise的结果,对于Promise的成功时回调函数的结果可以直接处理, 对于Promise的失败时回调函数的结果不能直接处理,但有两种解决方法:
第一种解决办法:通过Promise对象的catch()方法来定义失败时的回调函数,代码如下:
<script> function mydemo() { return new Promise((resolve, reject) => { setTimeout(() => { //需求:返回'Hello Web!!' console.log('Hello Web!!'); if (1) { // if (0) { resolve([true, 'Hello Web33333!!']); } else { reject('失败了'); } }, 3000); }); } async function myfn() { console.log('开始'); //第一种解决办法:通过Promise对象的catch()方法来定义失败时的回调函数 let data = await mydemo().catch(err => { console.log(err, 7777); }); console.log(data, '执行完成!!'); } myfn(); </script>
第二种解决办法:在Promise内部不管理执行成功或失败都调用成功时的回调方法resolve()方法,然后在resolve()方法中传递数组,数组的格式为:[true/false,值],代码如下:
<script> function mydemo() { return new Promise((resolve, reject) => { setTimeout(() => { //需求:返回'Hello Web!!' console.log('Hello Web!!'); if (1) { // if (0) { // resolve(); resolve([true, 'Hello Web33333!!']); } else { //第二种解决办法:在Promise内部不管理执行成功或失败都调用成功时的回调方法resolve()方法,然后在resolve()方法中传递数组,数组的格式为:[true/false,值] // reject('失败了'); resolve([false, '失败了']); } }, 3000); }); } async function myfn() { console.log('开始'); //第一种解决办法:通过Promise对象的catch()方法来定义失败时的回调函数 // let data = await mydemo().catch(err => { // console.log(err, 7777); // }); let [flg, data] = await mydemo(); if (flg) { console.log(data, '执行完成!!'); } else { console.log(data, '执行失败...'); } } myfn(); </script>
3.1 async函数基本用法
注意:async函数返回的也是一个promise对象
async函数的语法:
// 一般写法 async function name( ){ let res1 = await promise异步1 let res2 = await promise异步2 ... } // 箭头函数写法 async ()=>{ let res1 = await promise异步1 let res2 = await promise异步2 ... } // 在对象里面的写法 { async fn(){ let res1 = await promise异步1 let res2 = await promise异步2 ... } } // 点击函数写法 bnt.onclick = async ()=>{ let res1 = await promise异步1 let res2 = await promise异步2 ... }
代码案例:
<script> function demo() { } // console.log(demo()); // undefined async function fn() { } console.log(fn()); //async函数调用后返回的是Promise对象 // fn().then(d => { // console.log(d, 999); // }).catch(e => { // console.log(e); // }) </script>
3.2 应用
使用async函数把promise的异步变成真正的同步代码
代码案例:
<script> function mydemo() { return new Promise((resolve, reject) => { setTimeout(() => { //需求:返回'Hello Web!!' console.log('Hello Web!!'); if (1) { // if (0) { // resolve(); resolve([true, 'Hello Web33333!!']); } else { //第二种解决办法:在Promise内部不管理执行成功或失败都调用成功时的回调方法resolve()方法,然后在resolve()方法中传递数组,数组的格式为:[true/false,值] // reject('失败了'); resolve([false, '失败了']); } }, 3000); }); } async function myfn() { console.log('开始'); //第一种解决办法:通过Promise对象的catch()方法来定义失败时的回调函数 // let data = await mydemo().catch(err => { // console.log(err, 7777); // }); let [flg, data] = await mydemo(); if (flg) { console.log(data, '执行完成!!'); } else { console.log(data, '执行失败...'); } } myfn(); </script>
四、模块化封装数据库
(1)新建db.js文件并使用module.exports暴露方法,代码如下:【重点】
const mysql = require('mysql'); const mysqlObj = mysql.createConnection({ host: 'localhost', user: 'root', password: 'root', port: 3306, database: 'mydemo' }); mysqlObj.connect(); function exec(sql) { return new Promise((resolve, reject) => { mysqlObj.query(sql, (err, data) => { // console.log(err, data, 8888); //需求:返回data if (err) { //失败 resolve([false, err]); } else { //成功 resolve([true, data]); } }); }); } // exec('select * from xsb '); // exec(`insert into class(banji,teacher)values('php开发','王老师')`).then(d => { // let [flg, arr] = d; // }).catch(e => {}); // async function test() { // let sql = 'select * from xsb'; // let [err, datas] = await exec(sql); // if (err) { // console.log(datas); // for (let obj of datas) { // console.log(`姓名:${obj.xm} 所在系:${obj.szx}`); // } // } else { // console.log(`sql出错了:${datas}`); // } // } // test(); module.exports = exec;
(2),使用上面定义的db.js模块文件来操作msyql数据库,代码如下:
let mysqlExec = require('./6-dbMysql.js'); // console.log(mysqlExec); const express = require('express'); const app = express(); app.listen(4000, () => { console.log('4000端口'); }); app.get('/', async(req, res) => { let { xm = '' } = req.query; let sql = `select * from xsb where xm like '%${xm}%'`; // mysqlExec(sql).then().catch(); let [err, arr] = await mysqlExec(sql); console.log(err, arr); res.send(`查询结果为:${JSON.stringify(arr)}`); }); app.get('/dmeo', async(req, res) => { let sql = 'select * from cjb'; let [err, arr] = await mysqlExec(sql); });