资讯专栏INFORMATION COLUMN

COMBO--组合拳打穿回调地狱~

aristark / 3083人阅读

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

我想应该会有很多像我一样的前端听说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介绍

    摘要:最简单的监听办法就是使用使用格式如下它有两个参数,第一个参数是指定的单个按键或者组合键,第二个参数是一个回调函数,它在每一次用户按下指定的时被调用。 keypress.js是一个捕获键盘输入的JavaScript库,它简单易用,轻量级的压缩版本只有9kB左右,并且没有依赖其他JavaScript库。 我们通常用键盘事件来监听keydown和keyup事件。当按下键盘的任意键的时候,ke...

    cuieney 评论0 收藏0
  • 本命年一定要记得穿红裤衩:2015年总结

    摘要:年终总结结果到这个时间才写,其实也是无奈。这一年最重要的事情就是顺利从一只学生狗转职为一只社畜。四月份毕业之后以前端工程师的职位入职天猫,到现在也差不多工作一年了。 年终总结结果到这个时间才写,其实也是无奈。本来计划过年写的,没想到Steam竟然开了个农历春节特惠,然后就被各种游戏打了,辣鸡平台,敛我钱财,颓我精神,耗我青春,害我单身 以下全都是个人看法,如果有不认同的地方,请大吼一声...

    AlienZHOU 评论0 收藏0
  • 本命年一定要记得穿红裤衩:2015年总结

    摘要:年终总结结果到这个时间才写,其实也是无奈。这一年最重要的事情就是顺利从一只学生狗转职为一只社畜。四月份毕业之后以前端工程师的职位入职天猫,到现在也差不多工作一年了。 年终总结结果到这个时间才写,其实也是无奈。本来计划过年写的,没想到Steam竟然开了个农历春节特惠,然后就被各种游戏打了,辣鸡平台,敛我钱财,颓我精神,耗我青春,害我单身 以下全都是个人看法,如果有不认同的地方,请大吼一声...

    xi4oh4o 评论0 收藏0
  • 回调地狱-编写异步JavaScript指南

    摘要:什么是回调地狱异步代码,或者说使用的代码,很难符合我们的直观理解。人们理解回调的最大障碍在于理解一个程序的执行顺序。怎样解决回调地狱问题糟糕的编码习惯造成了回调地狱。把回调函数的第一个参数设置为对象,是中处理异常最流行的方式。 什么是回调地狱? 异步Javascript代码,或者说使用callback的Javascript代码,很难符合我们的直观理解。很多代码最终会写成这样: fs.r...

    刘玉平 评论0 收藏0
  • 《设计模式》3.结构型模式

    摘要:类的适配器结构目标角色这就是所期待得到的接口,由于是类适配器模式,因此目标不可以是类。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。和适配器模式的关系适配器模式的用意是改变所考虑对象的接口,而代理模式不能改变。 点击进入我的博客 3.1 适配器模式 适配器模式把一个类的接口变换成客户端所期待的另一种接口,使得原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 3...

    Yuqi 评论0 收藏0

发表评论

0条评论

aristark

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<