Я пытаюсь написать программу Node, которая заполняет мою базу данных MySQL данными из файлов, которые у меня есть на диске. Я могу или не могу так поступить правильно, но он работает. У меня возникают проблемы с пониманием того, как я должен работать, позволяя завершить асинхронные функции до завершения соединения с БД. В конечном счете, я буду читать множество файлов данных и вставлять их в базу данных, как я сделал ниже. Я могу просто использовать readFileSync
вместо асинхронной версии, но мне нужно получить лучший дескриптор асинхронных функций.Узел и MySQL: не удается завершить соединение -> Async confusion
Когда я вставляю следующие категории вин, он отлично работает, так как не использует асинхронную функцию. Однако, когда я использую readFile
, чтобы получить данные из файла, я получаю сообщение об ошибке, что соединение закончилось перед любым из запросов были выполнены:
connection.connect(function(err) {
if(err) {
console.log(err);
}
});
// Take a table and the values, and insert a new row into a table
function insert_into(table, values) {
if(values instanceof Array) {
values = values.map(function(value) {
return '"' + value + '"';
}).join(', ');
} else {
values = '"' + values + '"';
}
var statement = 'INSERT INTO ' + table + ' VALUES (NULL, ' + values + ')';
connection.query(statement, function(err, rows, fields) {
if (err) throw err;
console.log(values + " successfully added.");
});
};
// Populate the wine_categories table
var wine_categories = [
'red', 'white', 'rose', 'sparkling', 'fortified'
];
// Works fine when used alone
wine_categories.forEach(function(element) {
insert_into('wine_categories', element);
});
// Populate the countries table
// connection.end() runs before this finishes its job
fs.readFile(countries, 'utf8', function (err, data) {
if (err) {
throw err;
} else {
var codes = Array.prototype.map.call(
data.split('\n'), function(country) {
return country.split('\t');
});
codes.forEach(function(country) {
if(country[1].length > 25) {
country[1] = country[1].substring(0, 25);
}
insert_into('countries', country);
});
}
});
connection.end();
Очевидно, что connection.end()
должно произойти после того, как все вставки закончили, но Я не уверен, как с этим справиться. Я не хочу, чтобы это было обратным вызовом для вызова readFile
, потому что в конечном итоге у меня будет много похожих вызовов в этом файле.
Как я должен структурировать свой код, чтобы все запросы выполнялись, и connection.end()
запускается, когда все готово? Ответ, вероятно, очевиден для асинхронного wiz ...
Спасибо!При незначительной модификации формата 'country' это сработало. Пара задает вопросы: 1. Если у меня больше запросов на вставку, которые я хочу использовать, могу ли я просто добавлять '.concat (queryName)' в 'Promise.all'? 2. Если дополнительные таблицы имеют внешние ключи для заполняемых таблиц, мне нужно создать новый пул, который будет запущен после этого? – EmptyArsenal
@EmptyArsenal 'Promise.all' берет ряд обещаний и возвращает обещание, которое будет выполнено, когда выполняются все обещания в исходном массиве. Чтобы выполнить запрос, получите соединение из пула, затем используйте соединение для запуска запросов и, наконец, отпустите соединение. Например: http://pastebin.com/JhyvFhAS – Esailija
@EmptyArsenal вы можете сделать вспомогательную функцию, подобную этой, чтобы сделать ее еще проще. Http://pastebin.com/5twg6YE1 – Esailija