微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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会这样做.其背后的原因是,在瀑布中移动,添加删除步骤很困难,这是错误的根源.自动允许您添加步骤而不用担心,顺序/并行性由异步处理.

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐