Как правильно сделать несколько вызовов MySQL за один запрос с Node.js, Express.js, MySQL2 и Promises
Рассматривая правильный / лучший / лучший способ использования AWAIT с MySQL2 в приложении Node.js/Express.js, когда мне нужно выполнить несколько запросов в одном запросе.
В самом начале своего приложения я создаю пул Promise из конфигурации базы данных.
const promisePool = db.promise();
Затем в запросе POST я принимаю 2 значения, оба из которых мне нужно проверить, они действительны, а затем принимают возвращенные идентификаторы и вставляют их в другую таблицу.
Ниже была моя первая попытка, но я упускаю из виду JS одновременно. (Я чрезмерно упростил все вызовы /SQL для демонстрационных целей),
app.post('/addUserToDepartment', async (req, res) => {
// Get the POST variables
let email = 'example@example.com';
let departmentname = 'sales';
let insertParams = [];
// Need to check if Department ID is even valid
const [departments] = await promisePool.query( "SELECT ? AS deptid", [departmentname] );
// Need to check if Email address is valid
const [user] = await promisePool.query( "SELECT ? AS userid", [email] );
// This would normall be an INSERT or UPDATE statement
if(departments.length && user.length){
const [rows] = await promisePool.query( "SELECT ? AS passedDeptId,? AS passedUserid", [departments[0].deptid, user[0].userid] );
}
res.send( rows )
}
Вот мой второй удар по этому, теперь завершение обещаний.
app.post('/addUserToDepartment', async (req, res) => {
// Get the POST variables
let email = 'example@example.com';
let departmentname = 'sales';
let insertParams = [];
// Need to check if Department ID is even valid
let [[departments],[user]] =
await Promise.all([
promisePool.query( "SELECT ? AS deptid", [departmentname] ),
promisePool.query( "SELECT ? AS userid", [email] )
])
// This would normall be an INSERT or UPDATE statement
if(departments.length && user.length){
let [rows] = await promisePool.query( "SELECT ? AS passedDeptId,? AS passedUserid", [departments[0].deptid, user[0].userid] );
}
res.send( rows )
}
IF в конце все еще не "чувствует" себя правильно, но мне нужно знать, что первые два запроса верны, иначе я отправлю пользователя на страницу с ошибкой.
Что может быть лучшим способом для достижения вышеуказанного результата без потери читабельности?
2 ответа
Вот что я сделал в конце. Я добавил зацепки, а также выполнил последний запрос как часть цепочки Promise.all().
app.get('/test2', async (req, res) => {
// Get the POST variables
let email = 'example@example.com';
let departmentname = 'sales';
let insertParams = [];
let rtn = {
status : '',
errors : [],
values : []
}
console.clear();
// Need to check if Department ID is even valid
let arrayOfPromises = [
promisePool.query( "SELECT ? AS did", [departmentname] ),
promisePool.query( "SELECT ? AS uid", [email] )
]
await Promise.all(arrayOfPromises)
.then( ([d,u] ) => {
// Get the values back from the queries
let did = d[0][0].did;
let uid = u[0][0].uid;
let arrayOfValues = [did,uid];
// Check the values
if(did == 'sales'){
rtn.values.push( did );
} else{
rtn.errors.push( `${did} is not a valid department`);
}
if(uid == 'example@example.com'){
rtn.values.push( uid );
} else{
rtn.errors.push( `${did} is not a valid department`);
}
if( rtn.errors.length === 0){
return arrayOfValues;
} else{
return Promise.reject();
}
})
.then( async ( val ) => {
// By this point everything is ok
let [rows] = await promisePool.query( "SELECT ? AS passedDeptId,? AS passedUserid", val );
res.send( rtn )
})
.catch((err) => {
console.error(err)
rtn.status = 'APPLICATION ERROR';
rtn.errors.push( err.message);
res.send( rtn )
});
});
Во-первых: оба фрагмента сломаны как rows
переменная должна быть объявлена снаружи, если if
,
Помимо этого, то, что вы делаете, в основном хорошо, но большая проблема здесь в том, что если length
либо равно 0, вы ничего не возвращаете.
Это действительно то поведение, которое вы хотите? Если я позвоню /addUserToDepartment
и есть проблема в вашей базе данных, вы хотите, чтобы это молча провалилось?
Я думаю, что лучший подход - возвращать соответствующие ошибки, когда что-то идет не так. В идеале вы должны просто выбросить исключение (но вы используете Express, и я не уверен, поддерживают ли они перехват исключений).