#javascript #mysql #node.js #node-mysql
#javascript #mysql #node.js #узел-mysql
Вопрос:
У меня есть два запроса.
Первый,
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, чтобы получить count() элементов дешевле, чем 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 loop i var для добавления данных.
Как мне обойти это?
Редактировать: моя новая проблема:
Когда я ищу имя (searchobj), возвращаемые данные отстают на один шаг.
Скажем, я ищу «Tim», ничего не отображается.
Допустим, я ищу «Finn», затем отображаются мои данные о «Tim».
Я подозреваю, что это из-за того, как я получил данные из своей функции checkUndercut.
Я создал новую переменную верхнего уровня, 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
}
});
Консоль.журнал отправляет правильную информацию, поэтому моя проблема заключается в том, что функция 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.');
};
});
});
Мои вопросы:
- Каков правильный способ отправки данных из асинхронной функции?
- Есть ли какой-нибудь способ заставить мой app.get или res.send подождать, пока мои данные не будут получены перед их отправкой?
Редактировать 2: я могу заставить его работать, поместив весь код внутри моего app.get() , но должно быть более элегантное и простое для чтения решение?
Комментарии:
1. Каков ваш первый запрос? Я спрашиваю, потому что гораздо предпочтительнее объединить их в хранимую процедуру join / subselect, чем иметь много переходов назад и вперед к базе данных (это почти наверняка может накапливать данные для вас).).
2. Первый запрос выглядит следующим образом: ‘ВЫБЕРИТЕ auctions.name , wowitemdata.ItemName, auctions.ItemId, auctions.buyout, аукционы. количество ИЗ
auctions
ВНУТРЕННЕГО СОЕДИНЕНИЯwowitemdata
НА аукционах.ItemId = wowitemdata.ItemId ‘ Редактировать: Чертово форматирование
Ответ №1:
На мой взгляд, лучший способ сделать это — использовать модуль узла, вызываемый 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 /
Комментарии:
1. Я очень новичок в магии, которая является асинхронной, поэтому, пожалуйста, потерпите меня. У меня возникли проблемы с получением моей функции app.get для отправки данных в правильном порядке, с помощью (вероятно, обходного) способа, которым я «исправил» это, мои поиски отстают на один шаг. Скажем, я ищу «Tim», ничего не отображается. Допустим, я ищу «Finn», затем отображаются мои данные о «Tim». Я редактирую свой оригинальный пост, чтобы отразить эти новые вопросы.
Ответ №2:
попробуйте это
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 = resu<
var length = Object.keys(result).length;
console.log( length );
for (var i = 0; i < length; i )
{
console.log(result[i].column_name);
};
});
});
Ответ №3:
Если вы просто беспокоитесь о 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;
...
});
...
});