app.get("/loginForm?**",function(req,res){
pool.getConnection(function(err,connection){
if (err) {
console.log(err+"--from 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.query.username+"'";
connection.query(selectQuery,function(err,rows){
if (err) {
console.log(err+"--from query");
res.send("登录失败,数据库查询错误");
} else{
if (rows.length==0) {
res.send("登录失败,用户不存在");
} else{
if (req.query.password==rows[0].password) {
res.cookie("username",req.query.username,{
expires: new Date(Date.now() + 900000),
httpOnly:true
});/*res.cookie end*/
res.send("登录成功");
} else{
res.send("登录失败,密码不正确");
}
}
}
});
}
});
}
if(connection){connection.release()};
});
});
回调嵌套太多层导致很难维护了
根据一楼的回答我去实验了一下,首先是代码
//先promise化pool.getConnection
var getConn = new Promise(function(resolve,reject){
pool.getConnection(function(err,connection){
if (err) {
reject(err);
} else {
resolve(connection);
}
});
});
const test = async()=>{
let connection = await getConn;
console.log(connection);
};
这段直接运行会说async undefined
于是我把它babel一下
var _this = this;
var test = function test() {
var connection;
return regeneratorRuntime.async(function test$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.next = 2;
return regeneratorRuntime.awrap(getConn);
case 2:
connection = context$1$0.sent;
console.log(connection);
case 4:
case "end":
return context$1$0.stop();
}
}, null, _this);
};
运行test()后报错,说regeneratorRuntime undefined,我用的node5.6,不知道问题出在哪里
原来是因为babel依赖一个babel-polyfill的模块,require一下就好了。。。 但是新的问题又来了,pool.getConnction很容易就promise化了,但是connection.query由于依赖前者传回的connection,所以必须在async函数内部promise化才能使用。。。这就蛋疼了
const test = async()=>{
let connection = await getConn;
var conn = new Promise(function(resolve,reject){
connection.query("USE userInfo",function(err,rows){
if (err) {
reject(err);
} else {
resolve(rows);
}
});
});
let rows = await conn;
console.log(rows);
};
所以就变成这个造型了。。。。有什么办法能把connection.query在外部进行promise化么?
次最终方案出来了,如下
app.get("/loginForm?**", async (req, res) => {
try {
let connection = await getConn;
//promise化connection.query
var conn = function(queryString) {
var connPromise = new Promise(function(resolve, reject) {
connection.query(queryString, function(err, rows) {
if (err) {
reject(err);
} else {
resolve(rows);
}
});
});
return connPromise;
};
await conn("USE userInfo");
let selectQuery = "SELECT * FROM users WHERE userName=" + "'" + req.query.username + "'";
let rows = await conn(selectQuery);
if (rows.length === 0) throw '登录失败,用户不存在';
if (req.query.password !== rows[0].password) throw '登录失败,密码不正确';
res.cookie('username', req.query.username, {
expires: new Date(Date.now() + 15 * 60 * 1000),
httpOnly: true
});
res.send("登录成功");
connection.release();
} catch (e) { res.send(e); }
});
将其babel之后运行成功,为什么是次最终,主要是因为connection.query的promise化写在了主函数里面,显得代码很丑,希望能找到最终方案,让我通关回调地狱QAQ
async/await
只对 Promise 对象才有效。首先你要把数据库部分的各个方法改成 Promise 形式的。然后主函数就很简单了:别忘了这里的
pool.getConnection()
、connection.query()
都要 Promise 化。reject(err)
会被catch(e)
捕捉到,各种错误说明也是写在调用方法中的。对了,不管怎么样,原文哪种
if(err)-else
都是不需要的。对于这种有错就终止/返回函数的情况,只需要判断错误,不需要else
。