mysql回调地狱_COMBO--组合拳打穿回调地狱~

我想应该会有很多像我一样的前端听说js可以开发后台时,激动地踏上了node.js之路,这条路上第一个挑战,就是回调地狱。

app.get("/changePassword?**",function(req,res){

if(req.cookies.username){

pool.getConnection(function(err,connection){

if (err) {

console.log(err+"--from pool connection");

res.send("修改密码失败,数据库连接错误");

} else{

connection.query("USE userInfo",function(err,rows){

if (err) {

console.log(err+"--from using database");

res.send("修改密码失败,数据库使用错误");

} else{

var selectQuery = "SELECT * FROM users WHERE userName="+"'"+req.cookies.username+"'";

connection.query(selectQuery,function(err,rows){

if (err) {

console.log(err+"--from selectQuery");

res.send("修改密码失败,数据库查询错误");

} else{

if (req.query.password==rows[0].password) {

var updateQuery = "UPDATE users SET password="+"'"+req.query.newPassword+"' WHERE username="+"'"+req.cookies.username+"'";

connection.query(updateQuery,function(err,rows){

if (err) {

console.log(err+"--from updateQuery");

res.send("修改密码失败,数据库更新错误");

} else{

res.send("修改密码成功");

}

});/*connection.query update end*/

} else{

res.send("修改密码失败,原始密码错误");

}

}

});/*connection.query select end*/

}

});/*connection.query using database end*/

}

if(connection){connection.release()};

});/*pool.getConnection end*/

} else {

res.send("修改密码失败,登录失效");

}

});/*app.get end*/

这种造型的代码就是“邪恶金字塔”,或者说“回调地狱”,callback hell

我遇到的第一个障碍就是它,它让代码难以维护,难以修改,横向发展,非常不美观

于是我开始试图解决这个问题,为此,我求助了很多大神,看了很多帖子,被告知《ES6入门》这本书可以解决我的问题,于是从promise then到*yield到async/await

看到async/await我以为就皆大欢喜,问题解决了,然而nodejs目前需要babel转码才能使用async/await,很麻烦,而且对我这个新手很不友好。

在segmentfault上提问许久,发现有个asyncawait模块,可以模仿async/await模型来操作promise对象

npm install asyncawait

将如下代码添加到你的js文件中

var async = require("asyncawait/async");

var await = require("asyncawait/await");

var foo = async (function() {

var resultA = await (firstAsyncCall());

var resultB = await (secondAsyncCallUsing(resultA));

var resultC = await (thirdAsyncCallUsing(resultB));

return doSomethingWith(resultC);

});

await()里面可以放promise对象,也可以放异步回调函数,只要它有类似的返回机制,这样一来,就能提前使用async/await模式写代码了,一开始的回调地狱会变得如下代码一样,清晰易懂

//登录路由

app.get("/loginForm?**", async(function(req, res) {

try {

var connection = await(poolp.getConnection());

var selectQuery = "SELECT password FROM users WHERE username ='" + req.query.username + "'";

var rows = await(connection.query(selectQuery));

if (rows.length == 0) throw "登录失败,用户不存在";

if (rows[0].password != req.query.password) {

throw "登录失败,密码不正确";

} else {

res.send("登录成功");

}

} catch (err) {

res.send(err);

}

//记得释放connection,不然很快就会达到上限

if(connection) pool.releaseConnection(connection);

}));

不幸的是,await()里面放回调函数会使得代码很臃肿,如果放promise对象,就保持了与async/await模式的一致性。

nodejs的mysql模块,提供了pool,connection来操作数据库,可是它们都不是promise对象,我尝试自己封装成promise对象

var getConn = new Promise(function(resolve,reject){

pool.getConnection(function(err,connection){

if (err) {

reject(err);

} else {

resolve(connection);

}

});

});

var DBobj = function(connection){

this.connection = connection;

this.query = (queryString)=>{

var connPromise = new Promise(function(resolve, reject) {

this.connection.query(queryString, function(err, rows) {

if (err) {

reject(err);

} else {

resolve(rows);

}

});

});

return connPromise;

};

return this;

};

很蛋疼,而且DBobj无法正确返回对象,不过国外有大神早就解决了这个问题

npm install promise-mysql

var mysqlp = require('promise-mysql');

poolp = mysqlp.createPool({

host: 'localhost',

user: 'root',

password: 'root',

database: 'userInfo',

connectionLimit: 10

});

就这么将mysql提供的对象转化为了promise对象,于是上面的登录路由就可以运行了,简洁明了,要加正则或者别的什么验证随时都能加,只需要在两行代码之间插入逻辑,再也不用框起一大片代码然后调缩进了!

相应的,fs模块,mail模块也应该有promise版本,大家可以去npm上面搜索

最后,我希望我的文章能帮助像我一样的小白打败回调地狱,一起踏上nodejs的探索之旅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值