变量值在NodeJS ExpressJS中变为未定义

时间:2016-05-29 10:30:15

标签: mysql node.js express

我在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),但是,在外部,该值变为空(未定义),因为已经计算了其余代码。

我该如何解决这个问题? 提前谢谢。

3 个答案:

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