我是后端的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会这样做.其背后的原因是,在瀑布中移动,添加或删除步骤很困难,这是错误的根源.自动允许您添加步骤而不用担心,顺序/并行性由异步处理.
这显然使用了更多的垂直空间,但我认为这对于模块化来说是一个很小的代价.