node开发中,很多操作都是异步的,比如我们连接数据库,查询数据.首先,我们需要等待数据连接成功,然后要等待查询成功,也就是说在我们把从数据库查询到的结果返回到用户之前,至少需要经过两次回调.
回调函数除了剥夺了我们使用return和throw这些关键字,这种回调黑洞还会造成代码的可读性不强.代码复杂.为了解决这个问题,es6时候,出现了promise对象,es7中出现了async/await.这两种结合,很好的解决了上面的问题.
首先,我们了解promise对象.
promise对象是用来传递异步操作的消息,它代表了未来才会知道结果的事件(即程序中的异步操作).promise对象状态不受外界影响,它有三个状态,pending(进行中),resolved(已完成),rejected(已失败).它的状态只取决于异步操作的结果,并且一旦改变,就会不再修改.promise改变的情况有两种:
pending(进行中)==>resolved(已完成)
pending(进行中)==>rejected(已失败)
只要任何一种情况出现,promise的状态就已经定型,这时候,我们再对promise对象进行回调就即刻得到它的状态结果,(这时候的回调就是同步的).这种机制与事件是完全不同的,事件的特点是,如果错过了,再去监听,是获取不到结果的.
promise的使用很简单.
var promise =new promise(function(resolve,reject)){
if(success){
resolve()
}else{
reject()
}
}
promise.then((result) => { })
.catch((reason) => {});
从代码可以看出promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve方法和reject方法.resolve状态将prome对象状态从pending(进行中)改变为resolved(已完成),reject状态将prome对象状态从 pending(进行中)改变为rejected(已完成). promise.then和catch是处理成功和失败的方法.在then中我们可以return另一个promise,而在catch中,我们可以对多个异常更精准的捕获.
知道了promise的使用方法,我们针对文章开头讲的问题,来用promise就行优化.
首先,我们创建config.json文件,来同意保存mysql的配置
{
"mysql": {
"host": "",
"user": "",
"port": 3306,
"password": "",
"database": "",
"charset": "UTF8MB4_GENERAL_CI"
}
}
然后创建mysqlServer.js文件.来配置mysql自动连接池,等等公共方法
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
var bodyParser = require("body-parser");
var config = require("../config.json");
var pool = mysql.createPool(config.mysql);
router.use(bodyParser.json({
limit: "20000 kb"
}));
router.use(bodyParser.urlencoded({
parameterLimit: 1000,
limit: '50mb',
extended: false
}));
module.exports = pool;
接下来我们在写接口的js中,使用promise优化自动连接池和sql语句执行的回调.
//处理连接数据库
const connectionMysql = (sql) => {
return new Promise(function(resolve, reject) {
mysql.getConnection(function(err, connection) {
if (err) {
} else {
resolve(sqlSever(connection, sql))
}
});
});
}
//处理sql语句
const sqlSever = (connection, sql) => {
return new Promise(function(resolve, reject) {
connection.query(sql, function(err, rows, fields) {
if (err) {
console.log(err)
} else {
resolve(rows);
}
})
});
}
处理完之后,我们在写接口的时候,可以直接这样用
//使用Promise对异步处理
router.get('/getList', function(req, res, next) {
var sql = 'select title from test';
connectionMysql(sql)
.then((result) => {
var json = {
code: 200,
data: result
}
res.send(json);
})
.catch((reason) => {});
});
这样代码是不是简洁多了,当然,上面的两个方法是对所有接口公用的,我们可以单独提出来,当做共有方法.
Promise也有一些缺点,首先.当我们启动Promise之后,中途无法取消,其次,如果不设置回调函数,异常只会在Promise内部抛出,最后当处于pending(进行中)我们无法知道进度.
es7中的async/await是基于Promise来实现的,它同Promise一样都是非阻塞的,用来异步代码看起来想同步,但是async/await代码更简洁,对与异常处理也更加灵活,另外它能把Promise中的嵌套平铺避免了深层嵌套.(我们上面的代码就是深层嵌套).
下一篇文章,我们继续了解node中异步操作中另一种解决办法async/awai.
领取专属 10元无门槛券
私享最新 技术干货