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

发布时间:2019-08-11 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了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的探索之旅

脚本宝典总结

以上是脚本宝典为你收集整理的COMBO--组合拳打穿回调地狱~全部内容,希望文章能够帮你解决COMBO--组合拳打穿回调地狱~所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。