Node.js / Async – 如何避免使用异步回调地狱?

我是后端的Node.Js和 JavaScript Web开发的新手.我看到回调内部的回调可能很痛苦,并且有模块可以避免这种情况.其中一个模块是async,https://github.com/caolan/async

我已经阅读了文档,但很难开始并理解如何做到这一点.

例如,我有这个函数“check_aut_user”,如何使用async转换此代码

function check_auth_user(username,password,done) {

    var client = new pg.Client("pg://user:pass@127.0.0.1/database");
    client.connect(function(err) {
        // If not get the connection
        if(err) { return console.error('Could not connect to postgres',err); }

        // Query the user table
        client.query('select * from "user" where username = $1 and password = $2',[username,password],function(err,result) {
            if(err) { return console.error('error running query',err); }

            if (result.rowCount > 0) {
                var res = result.rows[0];
                console.log(res);

                passport.serializeUser(function(res,done) {
                    //console.log("serializer: " + res);
                    done(null,res);
                });

                passport.deserializeUser(function(user,done) {
                    //console.log("deserializer: " + user['password']);
                    done(null,res);
                }); 

                return done(null,res);
            } else {
                return done(null,false);
            }               
        });     
    });
}

最好的祝福,

解决方法

在我看来,回调地狱实际上是两个问题的混合:

>匿名内联函数.
>缩进.

少量的一个是好的,但它们一起使代码变得僵硬且不可维护.避免回调地狱的解决方案是通过以下方式避免这两件事:

>命名您的函数并将它们从函数调用中拉出来.
>早点回来以避免打算.

遵循这些原则,您的代码可以重写为:

function check_auth_user(username,done) {

    // Make a new client and open the connection.
    function connect(callback) {
        var client = new pg.Client("pg://user:pass@127.0.0.1/database");

        client.connect(function (err) {
            if (err) {
                console.error('Could not connect to postgres',err);
                return callback(err);
            }

            callback(null,client);
        });
    }

    // Query the database.
    function query(callback,results) {
        var client = results.client;
        var q = 'select * from "user" where username = $1 and password = $2';
        var params = [username,password];

        client.query(q,params,function (err,result) {
            if (err) {
                console.error('error running query',err.stack || err.message);
                return callback(err);
            }

            callback(null,result);
        });
    }

    // Do stuff with the result of the query.
    function handleQueryResult(callback,results) {
        var result = results.query;

        if (result.rowCount === 0) {
            return callback();
        }

        var row = result.rows[0];

        console.log(row);

        passport.serializeUser(function(res,done) {
            done(null,res);
        });

        passport.deserializeUser(function(user,res);
        }); 

        callback(null,row);
    }

    // Let async handle the order. Allows remixing.
    async.auto({
        connect: [connect],query: ['connect',query],row: ['query',handleQueryResult]
    },results) {
        if (err) {
            return done(err);
        }

        // Callback with the row.
        done(null,results.row);
    });
}

在这里使用过async.auto,即使async.waterfall会这样做.其背后的原因是,在瀑布中移动,添加删除步骤很困难,这是错误的根源.自动允许您添加步骤而不用担心,顺序/并行性由异步处理.

这显然使用了更多的垂直空间,但我认为这对于模块化来说是一个很小的代价.

相关文章

这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关...