我已经关注this tutorial,现在我正在构建一个连接到具有工作连接池的Mysql数据库的Express js应用程序;然后我在我的服务器中使用Async.js作为指令的瀑布。
我只是在重构我的代码,避免回调地狱。我很困惑,因为我有一个带有嵌套forEach函数的工作代码(回调地狱情况),它完美地获得了我的MySql连接,现在似乎没有任何工作。
问题: 收到GET请求后,它会打印到“动作二”并且它卡住。
这是我目前的 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的链异步指令的最佳可读解决方案。
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);
};
}
答案 0 :(得分:1)
如果由于某种原因,index === array.length-1
永远不会成立,那么您的代码将永远停留在actionTwo
,因为它的回调函数永远不会被调用。
此外,您似乎正在控制何时根据您要查询的阵列的索引调用actionTwo
回调。但这可能会导致错误。 connection.acquire
和con.query
都是异步的,因此位于最后一个索引并不能保证它是最后一个要返回的查询。如果对列表的最后一项的查询是最快的运行怎么办?
首先考虑声明所有SQL查询任务,然后使用其他async.js
函数控制其流程,例如async.parallel
或async.series
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?
}
}
});
}
}