2011-07-10 74 views
0

我知道node.js是事件驅動的,我應該這樣做,但我不能在我的腦海中找到一種方法來做到這一點。Node.js中的同步mysql

所以,我有這個

var querystr = "SELECT * FROM groups"; 
    var result = ""; 
    dbClient.query(querystr, function (err, res, fields) { 
     if (err) { 
      console.log(err); 
      return; 
     } 
     for(var i in res) { 
      result = result + "@" +res[i].name + " ="; 
      for (var j in res[i].members.split(",")) { 
       var memberquery; 
       if (j.substr(0,1) == "@") { 
        memberquery = "SELECT name FROM groups WHERE id = "+j.substr(1, j.length-1); 
       } else { 
        memberquery = "SELECT username FROM users WHERE id= "+j; 
       } 
       dbClient.query(memberquery, function(err, memres, fields) { 
        var membername = ""; 
        if (typeof memres[0].username == "undefined") { 
         membername = "@"+memres[0].name; 
        } else { 
         membername = memres[0].username; 
        } 
        result = result + " " + membername; 
       }); 

      } 
      result = result + "\n"; 
     } 
    }); 

,使得它同步的是對內部的問題。 基本上我生成結果變量的文檔,其中i檢查組和告訴成員所以預期輸出是

Group1 = member, member 
Group2 = member, member 
+0

夫婦快速旁白的:如果你做你的第一個查詢結果的第一通,以及環路成在第二通會員,你能避免SELECT名字從組查詢。另外,如果你的數據庫被正確地規範化了,你可以想象一個單一的查詢爲你做所有的表匹配工作。 – Metal

回答

3

我通常使用的圖案類似下面這種類型的問題。簡而言之:獲取一系列的東西然後調用一個函數來處理這個列表;該函數自行調用,直到列表完成;當你進入累加器時收集結果;當列表爲空時,返回通過回調積累的內容。這只是完成@Andrey Sidorov在回覆中表現出來的另一種方式。

//cb is (err, res) 
function getData(cb){ 
    var querystr = "SELECT * FROM groups"; 
    var result = ""; 

    dbClient.query(querystr, function (err, res, fields) { 
     if (err) 
      cb(err); 
     else { 
     var groups = []; 
     for (var ndx in res) 
      groups = groups.concat(res[ndx].members.split(",")); 

     getMembers(groups, [], cb); 
     } 
    }); 
} 

function getMembers(members, sofar, cb){ 
    var member = members.shift(); 

    if (!member) 
    cb(null, sofar); 
    else { 
    var memberquery; 
    var params; 

    if (member.substr(0,1) == "@") { 
     memberquery = "SELECT name FROM groups WHERE id = ?"; 
     params = [member.substr(1, member.length-1)]; 
    } else { 
     memberquery = "SELECT username FROM users WHERE id = ?"; 
     params = [member]; 
    } 

    dbClient.query(memberquery, params, function(err, res) { 
     if (err) 
     cb(err); 
     else { 
     var membername = ""; 
     if (typeof res[0].username == "undefined") { 
      membername = "@" + res[0].name; 
     } else { 
      membername = res[0].username; 
     } 

     sofar.push(membername); 

     getMembers(members, sofar, cb); 
     } 
    }); 
    } 
} 
+0

請注意,您的示例按順序調用查詢 –

+0

@Andrey爲true,儘管無論如何node-mysql將它們排隊,只有在前一個完成時才發出下一個請求 - 所以我認爲在這方面沒有多大區別。但是,你是對的,如果你使用了一個池並且可以同時向mysql發出查詢,你會得到一些並行化。 –

+0

感謝@Andrey和@Geoff,我認爲我刪除了這個問題,因爲我帶着一個解決方案來感謝async.js(好吧,它的一部分)。我使用的是像Geoff這樣的方法(實際上現在我有一個名爲getMembers的函數),但是我會去看另一個,因爲我不期待對輸出的響應,如果你是這樣的話,這可能是完全異步的 –

1
function do_queries(resultCallback) 
{ 
    var querystr = "SELECT * FROM groups"; 
    var result = ""; 
    var num_queries_left = 0; 
    dbClient.query(querystr, function (err, res, fields) { 
     if (err) { 
      console.log(err); 
      return; 
     } 

     // calculate number of invocations of second sub-query 
     for(var i in res) 
      num_queries_left += res[i].members.split(",").length; 

     for(var i in res) { 
      result = result + "@" +res[i].name + " =";     
      for (var j in res[i].members.split(",")) { 
       var memberquery; 
       if (j.substr(0,1) == "@") { 
        memberquery = "SELECT name FROM groups WHERE id = "+j.substr(1, j.length-1); 
       } else { 
        memberquery = "SELECT username FROM users WHERE id= "+j; 
       } 
       dbClient.query(memberquery, function(err, memres, fields) { 
        var membername = ""; 
        if (typeof memres[0].username == "undefined") { 
         membername = "@"+memres[0].name; 
        } else { 
         membername = memres[0].username; 
        } 
        result = result + " " + membername; 
        num_queries_left--; 
        if (num_queries_left == 0) 
        { 
         resultCallback(result); 
         return; 
        } 
       }); 

      } 
      result = result + "\n"; 
     } 
    }); 
} 


do_queries(function(result) { 
    console.log(result); 
});