在Async瀑布中为每个具有Mysql连接池的函数

我已经按照这个教程 ,现在我正在build立一个连接到一个Mysql数据库与一个工作连接池的Express js应用程序; 然后我使用Async.js在我的服务器中的瀑布指令。

我只是重构我的代码避免callback地狱。 我很困惑,因为我有一个嵌套的forEach函数(callback地狱的情况),它完全获得我的MySql连接的工作代码,现在没有任何工作。

问题:收到GET请求后,直到“Action Two”打印。

这是我目前的MWE

apiRoutes.get('/endpoint', function(req, res) { async.waterfall([ function actionOne(callback){ connection.acquire(function(err, con){ con.query( myQuery , function(err, result){ con.release(); if(err){ console.log(err); callback(err); } else { console.log("Action One Success"); callback(null, result); } }); }); }, function actionTwo(list, callback){ console.log("Action Two"); var arr = []; list.forEach(function(item, index, array){ item.arr = []; connection.acquire(function(err, con){ con.query( otherQuery , function(err, result){ con.release(); if(err){ console.log("SQL ERROR: "+err); callback(err); } else { item.arr = result; arr.push(cult); if(index === array.length-1){ console.log("Action Two Success"); callback(null, arr); } } } }); }) }, function actionThree(item, callback){ .... res.json('success'); }],function(err){ if(err) console.log(err); }); } 


求解:最后,我发现了使用Promises的链式asynchronous指令的最佳可读解决scheme。

 apiRoutes.get('/endpoint', function(req, res){ //Define 1st function function actionOne(){ return new Promise(function(fulfill, reject){ myAsyncQueryFunction(err, result){ if(err) { reject(err); } else { fulfill(result); } } } }; //Define 2nd function function actionTwo(){ return new Promise(function(fulfill, reject){ actionOne().then(function(result){ my2ndQueryFun(err, result){ if(err) { reject(err); } else { fulfill(result); } } }, reject); } }; //Execute async chained tasks, then send result to client actionTwo().then(function(result){ res.json(result); }; } 

如果由于某种原因, index === array.length-1永远不会是true,那么你的代码将永远停留在actionTwo因为它的callback函数永远不会被调用。

此外,似乎你正在控制什么时候根据你正在查询的数组的索引调用actionTwocallback。 但是这可能会导致错误。 connection.acquirecon.query都是asynchronous的,因此在最后一个索引处不保证它是最后一个返回的查询。 如果查询列表的最后一个项目是最快的一个运行?

考虑首先声明所有的SQL查询任务,然后使用另一个async.js函数(如async.parallelasync.series控制它们的stream

 function actionTwo(list, callback){ console.log("Action Two"); var tasks = []; list.forEach(function(item, index, array){ item.arr = []; tasks.push(async.apply(getDataFromSQL, item)); }) // could also be async.series(tasks, function (err, results) { // it depends if you want to run the queries in parallel or not async.parallel(tasks, function (err, results) { if (err) { console.log("Action Two Error") return callback(err); } console.log("Action Two Success"); return callback(null, results); //results is an array of the "cult" objects returned at each getDataFromSQL callback }); function getDataFromSQL(item, sqlCallback) { // otherQuery = generate_query_based_on_item(item); connection.acquire(function(err, con){ con.query( otherQuery , function(err, result){ con.release(); if(err){ console.log("SQL ERROR: "+err); sqlCallback(err); } else { item.arr = result; sqlCallback(null, cult); //not sure what cult meant. maybe result? } } }); } }