Node.js/Async - 如何避免异步回调 hell ?

标签 node.js node-async

我是后端 Node.Js 和 JavaScript 网络开发的新手。我看到回调中的回调可能会很痛苦,并且有一些模块可以避免这种情况。这些模块之一是异步的,https://github.com/caolan/async

我已阅读文档,但很难开始和理解如何去做。

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

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);
            }               
        });     
    });
}

最好的问候,

最佳答案

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

  • 匿名内联函数。
  • 缩进。

少量使用任何一种都可以,但它们一起会使代码变得僵硬且难以维护。避免回调 hell 的解决方案是通过以下方式避免这两件事:

  • 命名您的函数并将它们从函数调用中提取出来。
  • 早点返回以避免故意。

按照这些原则,您的代码可以重写为:

function check_auth_user(username, password, 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, done) {
            done(null, res);
        }); 

        callback(null, row);
    }

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

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

我用过 async.auto在这里,即使 async.waterfall 也行。其背后的原因是很难在 waterfall 中移动、添加或删除步骤,而这一直是错误的来源。 auto 让您无需担心添加步骤,顺序/并行性由异步处理。

这显然使用了更多的垂直空间,但我认为这是为模块化付出的很小的代价。

关于Node.js/Async - 如何避免异步回调 hell ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20961919/

相关文章:

javascript - NodeJS 发送数组的数组

javascript - Node.js 从流导入数据库后如何同步最终回调

node.js - 如何在有限制的情况下运行并行进程?

Node.js Selenium 找不到元素。没有这样的元素错误

sql - Pg- promise : transaction issue

json - Node.js 将大型 Xml 文件的 Xml 转换为 JSON 的示例

json - Twitter 流 api OAuth 未经授权

javascript - Node js eachOf循环中的mongodb查询

node.js - 延迟响应,直到所有查询完成

javascript - async.waterfall 仅返回函数数组的 array[0] 索引处的函数结果集 - Node js