Node.js中 promise与异步

本文详细介绍了如何使用Node.js通过mysql模块连接和操作MySQL数据库,包括Promise和异步编程的原理,如Promise的then/catch链式调用,以及async/await的使用。还展示了模块化封装数据库的方法,包括创建db.js文件和在应用中导入。
摘要由CSDN通过智能技术生成

一、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="请输入要查询的学生姓名">&nbsp;
        <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);
});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值