2つの質問があります。
最初、
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',
}
2番目のクエリは、#1のデータを使用して、itemIdよりも安いアイテムのcount()を取得します。応答は、新しい要素-> 'アンダーカット'として#1に追加されます。
私の機能:
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ループi変数を使用してデータを追加することはできません。
これを回避するにはどうすればよいですか?
編集:私の新しい問題:
名前(searchobj)を検索すると、返されるデータが1ステップ遅れます。
「Tim」を検索しても何も表示されません。
次に「Finn」を検索すると、「Tim」のデータが表示されます。
これは、checkUndercut関数からデータを取得する方法が原因だと思います。
新しいトップレベルのvar、appdataを作成し、@ 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.');
};
});
});
私の質問:
編集2:すべてのコードをapp.get()内に配置することで機能させることができますが、よりエレガントで読みやすいソリューションが必要ですか?
私の意見では、これを行う最良の方法は、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/
特定のインデックスの値を取得するための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;
...
});
...
});
これを試して
const connection = mysql.createConnection({
Host: 'localhost',
user: 'root',
password: 'pass',
database: 'db'
});
connection.connect(function(err)
{
if (err) throw err;
connection.query("SELECT * FROM tb", function (err, result, fields)
{
if (err) throw err;
var test = result;
var length = Object.keys(result).length;
console.log( length );
for (var i = 0; i < length; i++)
{
console.log(result[i].column_name);
};
});
});