SPRINT 11 . Работа с базами данных node.js. Последовательные запросы
Материалы
Текст
В предыдущих юнитах мы научились подключаться к базе данных в Node.js и получать данные из таблиц. Для выборки данных мы использовали пакет mysql и такой синтаксис:
conn.query(query, (err, result, field) =>{
console.log(err);
console.log(result);
// console.log(field);
});
Обратите внимание, что результат мы можем получить только внутри функции, там, где прописан console.log. Таким образом, если нам нужно сделать 2 последовательных запроса - то следующий запрос мы должны делать внутри функции коллбека. Т.е. так:
conn.query(query, (err, result, field) =>{
console.log(err);
console.log(result);
// console.log(field);
conn.query(query2, (err, result, field) =>{
console.log(err);
console.log(result);
// console.log(field);
});
});
Как видите, мы наблюдаем callbackhell или ад коллбеков. Даже при двух последовательных запросах - уже вложенность зашкаливает. Увы, очень часто приходится делать последовательные запросы к базе данных, и желательно избегать ада коллбеков.
Итак, наш кейс на сегодня - как сделать последовательные запросы в node.js (синхронные запросы к базе данных в node.js). Самое интересное, что если мы вспомним урок по чтению файлов то для файлов есть как синхронный, так и асинхронный запрос. Увы, с базой данной все сложнее.
Для решения используем пакет mysql2, установим его:
npm i mysql2
Подключим его, однако в отличие от предыдущих пакетов мы подключим его так:
const mysql = require('mysql2/promise');
Да, мы будем использовать Promise. Однако синтаксис promise очень громоздкий. Заменим его оберткой async await.
Создадим подключение к базе ( на примере локальной базы данных).
const config = {
host: "localhost", //127.0.0.1
user: "root",
database: "node_test",
password: ""
};
Давайте сделаем такую задачу. Пусть у нас в таблице user есть две строки, которые содержат firstname пользователей. Давайте мы вычитаем firstname пользователя с email test@ua и присвоим такое имя пользователю с email iv@ua. Причем сделаем это в виде двух последовательных операций.
Итак, мы будем пользоваться await, а данный синтаксис применим только async функциям. Напишем функцию вида:
async function main() {
const conn = await mysql.createConnection(config);
const [rows, fields] = await conn.execute('SELECT * FROM user where email="test@ua"');
console.log(rows[0]['firstname']);
await conn.execute('UPDATE user SET firstname="'+rows[0]['firstname']+'" WHERE email="iv@ua"');
conn.end();
}
Как видите мы изменили чуть структуру запроса. Теперь перед операцией conn.execute мы ставим await - тем самым сообщая о синхронном запросе. Результат мы получаем в rows. А во втором запросе мы тоже используем await и делаем его после первого. Если вы написали корректно, то во второй записи сменится имя.
Для того, чтобы функция сработала, мы должны ее вызвать.
main()
В некоторых случаях удобно возвращать результат для последующих операций. Тогда можно применять такой синтаксис.
async function main() {
const conn = await mysql.createConnection(config);
const [rows, fields] = await conn.execute('SELECT * FROM user ');
//console.log(rows);
conn.end();
return rows;
}
async function f() {
let a = await main();
console.log(a);
};
f();
Как видите вызывать async функцию тоже нужно через await внутри async функции.
Итак, мы научились делать последовательные запросы с минимальным синтаксисом в node.js.
TASKS
Для работы с базой данных используется mysql2.Все действия в задачах производим над таблицей user(таблицу создайте на основе файла node_unit_11.sql).Настройки подключения к базе данных должны быть вынесены в отдельный файл config.js и require в данный файл.
Напишите функцию f1(все функции в задании async), которая возвращает age пользователя с email = iv@ua.
Создайте функцию f2, которая возвращает coin (число) пользователя с возрастом 46.
Создайте функцию f3, которая возвращает true если у пользователя с lastname Petr монет больше 15 или false если меньше или равно.