我在mysql后端使用ExpressJS框架处理NodeJS。我在for循环中运行查询,然后我的循环和后续工作取决于查询的返回值。我对mysql查询不是很好,所以我通过for循环运行它。 问题是,由于异步[我猜!],for循环在查询结果出来之前很久就会结束。
这是我的代码:
function search_people_step2(user_id, search_criteria, user_friend)
{
var first_name_friends = [];
var last_name_friends = [];
for(var i = 0; i < user_friend.length; i++)
{
con.query("SELECT first_name, second_name FROM user WHERE userid = ?", user_friend[i],function(err, rows)
{
if(err)
{
//error;
}
else
{
if(rows.length == 0)
{
//nothing gets returned
}
else {
console.log(rows);
first_name_friends[i] = rows[0].first_name;
last_name_friends[i] = rows[0].second_name;
}
}
});
}
现在,我可以在查询语句中获取值(使用console.log),但是,在外部,该值变为空(未定义),因为已经计算了其余代码。
我该如何解决这个问题? 提前谢谢。
答案 0 :(得分:1)
simplest solution is
function search_people_step2(user_id, search_criteria, user_friend)
{
var first_name_friends = [];
var last_name_friends = [];
for(var i = 0; i < user_friend.length; i++)
{
con.query("SELECT first_name, second_name FROM user WHERE userid = ?", user_friend[i],function(err, rows)
{
if(err)
{
//error;
}
else
{
if(rows.length == 0)
{
//nothing gets returned
}
else {
console.log(rows);
first_name_friends[i] = rows[0].first_name;
last_name_friends[i] = rows[0].second_name;
}
if(i==user_friend.length-1){
//do your work here which you want to perform in end
}
}
});
}
或使用异步库
var async = require('async');
var first_name_friends = [];
var last_name_friends = [];
async.series([function(cb){
function search_people_step2(user_id, search_criteria, user_friend)
{
for(var i = 0; i < user_friend.length; i++)
{
con.query("SELECT first_name, second_name FROM user WHERE userid = ?", user_friend[i],function(err, rows)
{
if(err)
{
//error;
}
else
{
if(rows.length == 0)
{
//nothing gets returned
}
else {
console.log(rows);
first_name_friends[i] = rows[0].first_name;
last_name_friends[i] = rows[0].second_name;
}
if(i==user_friend.length-1){
cb()
}
}
});
}
},function(cb){
//do your work here
}],function(err){})
答案 1 :(得分:1)
你是对的,你的问题是mysql调用的异步性质。您必须为search_people_step2
功能提供回调。
你可以改变它:
search_people_step2(user_id, search_criteria, user_friend, callback)
在您的函数体中,您可以使用名为async的库来正确处理所有回调。以下是用法示例:
async.eachSeries(user_friend, function(item, eachCb){
con.query("SELECT first_name, second_name FROM user WHERE userid = ?",
user_friend[i],function(err, rows) {
if(err) {
eachCb('error');
}
else {
if(rows.length == 0){
//nothing gets returned
eachCb(null);
}
else {
console.log(rows);
first_name_friends.push(rows[0].first_name);
last_name_friends.push(rows[0].second_name);
eachCb(null);
}
}
}, callback);
});
这会在数组的每个项目上按顺序调用每个查询,并在完成后调用内部回调。处理完所有项目或发生错误时,将调用外部回调。有关更多文档,请参阅async库。
答案 2 :(得分:1)
我在你的代码中发现的第一件事就是你没有在SQL查询中使用IN
语句(虽然与你的问题没有直接关系),这意味着你发出了尽可能多的请求。 user_friend
中的条目。问题是SQL库是异步实现的,你无法避免它。但是你可以使用ES6功能Promises优雅地处理它:
(我没有测试代码,但我认为它应该可以工作)
function search_people_step2(user_id, search_criteria, user_friend)
{
return new Promise((resolve,reject)=>{
var first_name_friends = [];
var last_name_friends = [];
var placeHolders=user_friend.map(()=>"?").join(",");
con.query("SELECT first_name, second_name FROM user WHERE userid IN ("+placeHolders+")",user_friend,(err,rows)=>{
if(err)
reject(err);
else{
rows.forEach(row=>{
first_name_friends.push(row.first_name);
last_name_friends.push(row.second_name);
});
resolve({first_name_friends,last_name_friends});
}
});
});
}
并按照以下方式调用您的函数:
search_people_step2(id,crit,friends).then(result=>{
//handle result asynchronously as there is no choice
console.log(result.first_name_friends);
console.log(result.last_name_friends);
}).catch(err=>{
//handle error
});