摘要:我想应该会有很多像我一样的前端听说可以开发后台时,激动地踏上了之路,这条路上第一个挑战,就是回调地狱。
我想应该会有很多像我一样的前端听说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的探索之旅
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/78864.html
摘要:最简单的监听办法就是使用使用格式如下它有两个参数,第一个参数是指定的单个按键或者组合键,第二个参数是一个回调函数,它在每一次用户按下指定的时被调用。 keypress.js是一个捕获键盘输入的JavaScript库,它简单易用,轻量级的压缩版本只有9kB左右,并且没有依赖其他JavaScript库。 我们通常用键盘事件来监听keydown和keyup事件。当按下键盘的任意键的时候,ke...
摘要:年终总结结果到这个时间才写,其实也是无奈。这一年最重要的事情就是顺利从一只学生狗转职为一只社畜。四月份毕业之后以前端工程师的职位入职天猫,到现在也差不多工作一年了。 年终总结结果到这个时间才写,其实也是无奈。本来计划过年写的,没想到Steam竟然开了个农历春节特惠,然后就被各种游戏打了,辣鸡平台,敛我钱财,颓我精神,耗我青春,害我单身 以下全都是个人看法,如果有不认同的地方,请大吼一声...
摘要:年终总结结果到这个时间才写,其实也是无奈。这一年最重要的事情就是顺利从一只学生狗转职为一只社畜。四月份毕业之后以前端工程师的职位入职天猫,到现在也差不多工作一年了。 年终总结结果到这个时间才写,其实也是无奈。本来计划过年写的,没想到Steam竟然开了个农历春节特惠,然后就被各种游戏打了,辣鸡平台,敛我钱财,颓我精神,耗我青春,害我单身 以下全都是个人看法,如果有不认同的地方,请大吼一声...
摘要:什么是回调地狱异步代码,或者说使用的代码,很难符合我们的直观理解。人们理解回调的最大障碍在于理解一个程序的执行顺序。怎样解决回调地狱问题糟糕的编码习惯造成了回调地狱。把回调函数的第一个参数设置为对象,是中处理异常最流行的方式。 什么是回调地狱? 异步Javascript代码,或者说使用callback的Javascript代码,很难符合我们的直观理解。很多代码最终会写成这样: fs.r...
摘要:类的适配器结构目标角色这就是所期待得到的接口,由于是类适配器模式,因此目标不可以是类。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。和适配器模式的关系适配器模式的用意是改变所考虑对象的接口,而代理模式不能改变。 点击进入我的博客 3.1 适配器模式 适配器模式把一个类的接口变换成客户端所期待的另一种接口,使得原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 3...
阅读 2511·2021-10-12 10:12
阅读 759·2019-08-29 17:25
阅读 2754·2019-08-29 17:24
阅读 3178·2019-08-29 17:19
阅读 1773·2019-08-29 15:39
阅读 2998·2019-08-26 16:50
阅读 1946·2019-08-26 12:17
阅读 2679·2019-08-26 12:16