2016-10-13 103 views
3

我有兩個查詢。
第一,node.js mysql for循環查詢

SELECT auctions.name, wowitemdata.itemName, auctions.itemId, 
auctions.buyout, auctions.quantity 
FROM auctions 
INNER JOIN wowitemdata ON auctions.itemId = wowitemdata.itemID; 

返回的數據是這樣的:

{ 
name: 'somename', 
itemName: 'someitemname', 
itemId: '0000', 
buyout: '0001', 
quantity: '5', 
} 

第二屆查詢從#1的數據來獲得項目比的itemId便宜的計數()。響應將作爲新元素添加到#1 - >'undercut'。

我的功能:

function checkUndercut(data, length){ 
    var Select = 'SELECT COUNT(auctions.itemId) AS cnt '; 
    var From = 'From `auctions` '; 
    var Where = 'WHERE auctions.itemId LIKE ? AND buyout < ?'; 
    var sql = Select + From + Where; 
    for(i = 0, len = length; i < len; i++){ 
     var inserts = [data[i]['itemId'], data[i]['buyout']]; 
     var ssql = mysql.format(sql, inserts); 
     data[i]['undercut'] = i; 
     connection.query(ssql, function(err, rows, fields){ 
      if(!err){ 
       console.log("check Undercut: " + rows[0].cnt); 
       data[i]['undercut'] = rows[0].cnt; 
      } else { 
       console.log("Error while performing Query"); 
      }; 
     }); 
    }; 
} 

由於查詢的異步性,我不能用for循環我VAR追加數據。
我該如何解決這個問題?

編輯: 我的新的問題:
當我搜索的域名(searchobj),返回的數據是落後一步。
說我搜索「蒂姆」,什麼都沒有出現。
說我接下來搜索「Finn」,我的關於「Tim」的數據出現了。

我懷疑這是因爲我從checkUndercut函數中獲取數據的方式。
我做了一個新的頂級變種,應用程序數據和使用@simple_programmers建議後,我把我的新代碼:

function(err){ 
     if(err){ 
      //handle the error if the query throws an error 
     }else{ 
      appdata = data; 
      console.log(appdata); 
      //whatever you wanna do after all the iterations are done 
     } 
    }); 

的執行console.log發出正確的信息,所以我的問題在於get函數發送反應過早。

我get函數:

app.get('/test',function(req, res) { 
    console.log("app.get "+searchobj); 
    var sqlSELECT = 'SELECT auctions.name, wowitemdata.itemName, auctions.itemId, auctions.buyout, auctions.quantity '; 
    var sqlFROM = 'FROM `auctions` '; 
    var sqlINNER ='INNER JOIN `wowitemdata` ON auctions.itemId = wowitemdata.itemID '; 
    var sqlWHERE = 'WHERE auctions.name LIKE ?'; 
    var sql = sqlSELECT + sqlFROM + sqlINNER + sqlWHERE; 
    var inserts = [searchobj]; 
    var sql = mysql.format(sql, inserts); 
    //console.log("Query: "+sql); 
    connection.query(sql, function(err, rows, fields) { 
     if (!err){ 
     var rowLen = rows.length; 
     checkUndercut(rows, rowLen); 
     console.log(appdata); 
     res.send(appdata); 
       } else { 
    console.log('Error while performing Query.'); 
    }; 

    }); 
}); 

我的問題:

1什麼是發送數據了異步函數的正確方法是什麼?

2有什麼方法可以讓我的app.get或res.send等待直到我的數據在發送之前被檢索?

編輯2:我可以通過將所有代碼放在我的app.get()中來獲得它的工作,但是必須有更優雅和更易於閱讀的解決方案嗎?

+0

什麼是你的第一個查詢?我問,因爲它非常適合將它們放在一起存儲過程,加入/再選擇,而不是多次來回數據庫(它幾乎可以爲你積累數據)。 – msanford

+0

第一個查詢是這樣的: 'SELECT auctions.name,wowitemdata.itemName,auctions.itemId,auctions.buyout,auctions.quantity FROM'auctions' INNER JOIN'wowitemdata' ON auctions.itemId = wowitemdata.itemID' 編輯:該死的格式化 – user45706

回答

4

在我看來,要做到這一點,最好的方法是使用所謂的async並行運行的東西,有一個回調,當一切都完成一個節點模塊。

在這種情況下有async模塊中定義的各種方法,我推薦的方法是forEachOf

鑑於您的data參數是一個數組,它是這樣的東西 -

function checkUndercut(data, length){ 
    var Select = 'SELECT COUNT(auctions.itemId) AS cnt '; 
    var From = 'From `auctions` '; 
    var Where = 'WHERE auctions.itemId LIKE ? AND buyout < ?'; 
    var sql = Select + From + Where; 
    async.forEachOf(data, function (dataElement, i, inner_callback){ 
     var inserts = [dataElement['itemId'], dataElement['buyout']]; 
     var ssql = mysql.format(sql, inserts); 
     dataElement['undercut'] = i; 
     connection.query(ssql, function(err, rows, fields){ 
      if(!err){ 
       console.log("check Undercut: " + rows[0].cnt); 
       dataElement['undercut'] = rows[0].cnt; 
       inner_callback(null); 
      } else { 
       console.log("Error while performing Query"); 
       inner_callback(err); 
      }; 
     }); 
    }, function(err){ 
     if(err){ 
      //handle the error if the query throws an error 
     }else{ 
      //whatever you wanna do after all the iterations are done 
     } 
    }); 
} 

那麼,什麼是主要的作用是,它遍歷您data陣列並運行該陣列的每個元素的查詢。一旦查詢被執行,它就會調用本地迭代的回調方法。一旦完成了所有迭代(即最後一次本地回調被調用),它會調用最後一次回調,在所有查詢執行完畢後,您可以隨後執行任何您想要執行的操作。

更多forEachOf這裏 - https://caolan.github.io/async/docs.html#eachOf

異步模塊 - https://caolan.github.io/async/

+0

我對異步的魔法很陌生,所以請耐心等待。 我無法讓我的app.get函數以正確的順序發送數據,並且(可能是迂迴曲折的)我「固定」它的方式,我的搜索是落後一步。假設我搜索「Tim」,則什麼也沒有顯示出來。 說我搜索「芬蘭人」接下來,我的數據「蒂姆」出現。 我正在編輯我的原始文章以反映這些新問題。 – user45706

0

如果您只是在擔心i的範圍以達到某個特定索引的值,請使用array.forEach

data.forEach(function(datum, i){ 
    var inserts = [datum['itemId'], datum['buyout']]; 
    var ssql = mysql.format(sql, inserts); 
    datum['undercut'] = i; 
    connection.query(ssql, function(err, rows, fields){ 
    ... 
    datum['undercut'] = rows[0].cnt; 
    ... 
    }); 
    ... 
});