2016-05-29 5 views
0

Я работаю с NodeJS, используя среду ExpressJS в бэкэнд mysql. Я запускаю запрос внутри цикла for, и мой цикл и работа потом зависят от возвращаемого значения запроса. Я не очень хорошо разбираюсь в mysql-запросе, поэтому я запускаю его через цикл for. Проблема заключается в том, что из-за асинхронности [я думаю!] Цикл for заканчивается задолго до вывода результата запроса.значение переменной становится неопределенным в NodeJS ExpressJS

Вот мой код:

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

You не может, кроме случаев, когда существует синхронный метод для выполнения запроса. – n00dl3

+0

Как написать синхронный метод в JS? –

+0

Вы не можете, так как это зависит от реализации sql. Вы могли бы использовать обещания, если вы действительно хотите вернуть что-то ... – n00dl3

ответ

1

Первое, что я нахожу странным в вашем коде, - это то, что вы не используете оператор IN в своем SQL-запросе (не связанный напрямую с вашей проблемой), что означает, что вы делаете столько запросов, сколько записей в user_friend , Проблема в том, что библиотека SQL реализована асинхронно, и вы не можете ее избежать. НО вы можете справиться элегантно с Promises которые ES6 особенности: (я не проверял код, но я думаю, что он должен работать)

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 
}); 
+0

мой NodeJS выдает ошибку, когда я вызываю функцию поиска в result => (для знака>) ..... –

+0

Какая именно ошибка, пожалуйста? и какова ваша версия nodejs? – n00dl3

+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

Вы правы, ваша проблема в том, асинхронная природа вызова 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); 
}); 

Это вызывает каждый запрос в порядке по каждому элементу массива и вызывает внутреннюю функцию обратного вызова, если закончено. Когда все элементы обрабатываются или возникает ошибка, вызывается внешний обратный вызов. См. Асинхронную библиотеку для дальнейшей документации.

+0

Какова может быть функция обратного вызова? что означало u для каждого CB? В каждом обратном вызове я перехожу к своей функции search_result _....? –

+0

«callback» - это функция, переданная от вызова search_people .... Вы можете заменить третий аргумент на асинхронный.eachSeries с помощью функции анонимной функции (err) {// делать что-то после завершения всего}, а затем вызывать обратный вызов из search_people ....; Каждый элемент Cb является обратным вызовом для каждого элемента. Дополнительную информацию см. В связанной документации. – yoyobo

Смежные вопросы