NodeJS异步编程解决方案
在JS里面,异步编程是JS的基础,我们会看到很多代码都是异步执行的,例如jQuery里面的动画 ,Ajax里面的请,MySQL与WebSQL的数据库操作,像这些都是异步。
在之前的异步编程里面,我们使用的解决方案都是回调,例如jQuery里面的动画回调, Ajax里面的回调,MySQL操作的回调,setTimtout也是一个异步的。
在最开始的异步解决方案里面,我们使用的是回调来解决异步的返回值的问题,今天我们把前端常见的三种异步解决方案总结一下
回调方法解决异步编程
回调的使用场景非常多,它既可以解决控制权的问题,也可以解决异步的问题,现在我们使用setTimeout
的方式来模拟一个异步操作
function abc(callBack) {
//我们使用setTimeout 5秒钟以后,生成一个0~100之间的随机数,
//如果这个随机数大于60,则返回及格 ,否则返回不及格
setTimeout(() => {
let temp = parseInt(Math.random() * 100);
let result = temp >= 60 ? "及格" : "不及格";
if (typeof callBack == "function") {
callBack(result);
}
}, 5000);
}
abc(result => {
console.log(`你的成绩是: ${result}`);
});
我们将之前封装的DBUtil.js
的代码使用回调完成一次
DBUtils.js代码
const mysql = require("mysql");
/**
* @class DBUtil
* @description 数据库操作核心对象
*/
class DBUtil {
/**
* @name getConn 获取数据库连接
* @description 静态方法,获取数据库的连接
* @returns {object} conn数据库连接
*/
static getConn() {
let conn = mysql.createConnection({
host: "127.0.0.1",
port: 3306,
user: "root",
password: "aaabbb",
database: "test",
multipleStatements: true
});
conn.connect();
return conn;
}
/**
*
* @param {string} strSql 要执行的SQL语句
* @param {function} callBack 执行SQL语句以后的回调操作
* @param {Array} params 执行SQL语句所需要的参数
*/
static executeSql(strSql, callBack, params = []) {
let conn = DBUtil.getConn();
conn.query(strSql, params, (err, result) => {
if(typeof callBack=="function"){
callBack(err,result);
}
conn.end();
});
}
}
module.exports=DBUtil;
调用上面的方法进行测试
const DBUtil=require("./utils/DBUtil.js");
function abc(){
let strSql="select * from stuinfo";
DBUtil.executeSql(strSql,(err,result)=>{
if(err){
//说明数据库执行失败了
console.log(err);
}
else{
//说明数据库执行成功了
console.log(result);
}
});
}
abc();
NodeJS里面使用事件对象解决
在NodeJS里面自带的模块包里面有一个模块包叫events
,这个包是事件包
方法的本质可以理解为“用户触发事件,事件调用方法”。当用户去触发这个事件的时候,事件就会调用一个方法,所以我们可以根据一个像这样的思路去完成异步操作
/**
* 异步编程第二种解决方案 events事件
*/
//我们使用setTimeout 5秒钟以后,生成一个0~100之间的随机数,
//如果这个随机数大于60,则返回及格 ,否则返回不及格
//使用NodeJS自带的模块包
const events = require("events");
function abc() {
//创建一个事件出来
let event = new events.EventEmitter();
setTimeout(() => {
let temp = parseInt(Math.random() * 100);
if(temp<60){
event.emit("catch","不及格");
}
else{
event.emit("then","及格");
}
}, 1000);
return event; //返回刚刚创建的事件对象
}
abc().on("then",result=>{
console.log(result);
}).on("catch",err=>{
console.log(err);
});
现在我们通过这个方法来封装数据库的异步操作
DBUtils.js代码
const mysql = require("mysql");
const events = require("events");
/**
* @class DBUtil
* @description 数据库操作核心对象
*/
class DBUtil {
/**
* @name getConn 获取数据库连接
* @description 静态方法,获取数据库的连接
* @returns {object} conn数据库连接
*/
static getConn() {
let conn = mysql.createConnection({
host: "127.0.0.1",
port: 3306,
user: "root",
password: "aaabbb",
database: "test",
multipleStatements: true
});
conn.connect();
return conn;
}
/**
*
* @param {string} strSql 要执行的SQL语句
* @param {function} callBack 执行SQL语句以后的回调操作
* @param {Array} params 执行SQL语句所需要的参数
*/
static executeSql(strSql, params = []) {
let event=new events.EventEmitter();
let conn = DBUtil.getConn();
conn.query(strSql, params, (err, result) => {
if(err){
event.emit("catch",err);
}
else{
event.emit("then",result);
}
conn.end();
});
return event;
}
}
module.exports = DBUtil;
测试上面的方法
const DBUtil=require("./utils/DBUtil2.js");
function abc(){
let strSql="select * from stuinfo";
DBUtil.executeSql(strSql).on("then",result=>{
//代表数据库执行成功
console.log(result);
}).on("catch",err=>{
//代表数据库执行失败
console.log(err);
});
}
abc()
注意:events
是NodeJS的自带模块,只能在NodeJS里面使用,如果想在浏览器的环境下面去使用我们需要下载第三方框架,例如onfire.js
框架
使用ES6里面的Promise解决
Promise是ES6里面新出的对象,用用于处理异步编程的,它是一个构造函数,本内自带三个状态(具体可以看之前的笔记)
/**
* 使用promise来解决异步编程
*/
function abc() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
let temp = parseInt(Math.random() * 100);
if (temp < 60) {
//拒绝
reject("你的分数不够,不能参加科目二考试 ,请回去好好学习");
} else {
//继续
resolve(temp);
}
}, 1000);
});
return promise;
}
abc().then(result=>{
//代表resolve的结果
console.log(`你的得分得:${result},可以继续下一轮考试`);
}).catch(err=>{
//代表reject的结果
console.log(`拒绝操作,原因是:${err}`);
})
上面的代码使用了promise的方式来进行,在ES6里面,promise可以转换为同步代码
上面的代码转换为同步以后,如下所示
/**
* 使用promise来解决异步编程
*/
function abc() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
let temp = parseInt(Math.random() * 100);
if (temp < 60) {
//拒绝
reject("你的分数不够,不能参加科目二考试 ,请回去好好学习");
} else {
//继续
resolve(temp);
}
}, 1000);
});
return promise;
}
async function def() {
try {
let result = await abc();
console.log(`你的得分得:${result},可以继续下一轮考试`);
}
catch (err) {
console.log(`拒绝操作,原因是:${err}`);
}
}
def();
await
不能暴露在全局使用,并且在async
的方法里面使用await
等待到的只能是resolve()
的结果,如果是reject()
会自动跳到catch
的异常里面去
评论区