2016-05-29 51 views
0

我正在使用ExpressJS框架的NodeJS在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

你除了如果有一個同步方法來執行查詢。 – n00dl3

+0

如何在JS中編寫同步方法? –

+0

你不能,因爲它取決於sql的實現。你可以使用承諾,如果你真的想返回somthing ... – n00dl3

回答

1

,我覺得在你的代碼奇怪的第一件事是,你不使用你的SQL查詢的IN聲明(不直接關係到你的問題雖然)這意味着,因爲在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

當我在result =>(for>符號)中調用搜索函數時,我的NodeJS發生錯誤..... –

+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

什麼是回撥功能?每個CB意味着什麼? 在每個回調中,我是否會回到我自己的函數search_result _....? –

+0

「callback」是從調用傳遞給search_people的函數。您可以將第三個參數替換爲異步。eachSeries由一個匿名函數函數(err){//在所有事情完成後做一些事情},然後從search_people調用回調函數.... eachCb是每個項目的回調。有關更多詳細信息,請參閱鏈接文檔 – yoyobo