#node.js #asynchronous #mariadb
#node.js #асинхронный #mariadb
Вопрос:
Это мой код:
const mariadb = require('mariadb');
var test = async function(){
var ret = "";
await mariadb.createConnection({
host: "localhost",
user: "dave",
connectionLimit: 5,
password: "!@#",
database: "db",
rowsAsArray: false
}).then((data)=>{
ret = "test";
});
return ret;
}
console.log(test());
Как я могу получить возврат из then с помощью await?
Я знаю, что подобные вопросы поднимались во многих случаях, но я не смог найти ни одного с помощью mariadb.
Ответ №1:
Я уже вижу несколько подводных камней, с которыми вы, как новички, столкнетесь в этом коде:
avait
ожидает возврата результатов, так как он получитPromisses
для ее решенияthen
решает обещания асинхронно- функция, определенная как
async
всегда возвращает обещания
После минутного восторга ‘async / await’ теперь я стараюсь избегать его. Главным образом потому, что каждая функция, в которой я использую асинхронную функцию, также должна быть асинхронной, пока вы не используете then
, например, сделайте небольшой тест:
let test = async function() {
let x = await 11
return 1;
}
console.log(test()) //returns: Promise { <pending> }
Там нет ничего асинхронного, но добавление async / await
вызвало беспорядок.
Теперь исправлены ошибки в вашем коде
const mariadb = require('mariadb');
// use local scope `let` instead global `var`
let test = async function(){
let conn = await mariadb.createConnection({
host: "localhost",
user: "dave",
connectionLimit: 5,
password: "!@#",
database: "db",
rowsAsArray: false
});
return conn.query("SELECT 1 as val") // no sense using `avait` because `test()` returns `promise`
}
test().then(function(rows) { console.log(rows)});
и без asnc. then
может возвращать обещание, и это может быть разрешено следующим then
mariadb.createConnection(...).then(conn => { // create connection
return conn.query("SELECT 1 as val") // make query
}).then(rows => { //get result
console.log(rows)
}).catch(err => console.error(err)) // get errors
Кстати: заинтересовался построителем запросов, например knex.js . Это позволяет писать код, независимый от database engine.
Обновить
Начнем с того, что Node основан на событиях.
Давайте рассмотрим пример получения данных из базы данных. В PHP / C вы делаете запрос, ждете, получаете результат. И это поведение имитируется с помощью await
. (Ожидание появилось где-то около версии 8)
Обычно код в Node работает так, что вы выполняете запрос, и Node создает новый поток. Старая команда запустите next, в новой вы получите результаты. (ОК, я вру, но это проще объяснить).
Итак, вы должны обработать событие получения данных. И, более конкретно, promise
предоставления данных. С помощью await
, .then ()
или callback (hell)
первое объяснение кода:
Вы пытаетесь вернуть ret
, но этот код сначала выполняется return ret
, а после выполняется присваивание.
await
«возвращает» данные, поэтому вам следует использовать let var_name = await asyncFunction()
Я предполагаю, что вы хотите этого:
let getSomeDataFromDB = function(){
return mariadb.createConnection([skip]).then(conn => {
return conn.query("SELECT 1 as val")
})
}
let rows = await getSomeDataFromDB()
В этой функции вы возвращаете promise, которые возвращают promise. И await
эта цепочка обещаний разрешена.
Но вот «небольшая» ошибка в коде. Потому что вы подключаетесь и нигде не прерываете свое соединение. Поэтому лучше иметь глобальный объект connection или использовать что-то вроде этого:
let getSomeDataFromDB = function(){
return new Promise(function(resolve, reject){
mariadb.createConnection([skip]).then(conn => {
conn.query("SELECT 1 as val")
.then(rows=>resolve(rows))
.catch(e=>reject(e))
.then(()=>conn.close())
}).catch(e => reject(e))
})
}
let rows = await getSomeDataFromDB()
И здесь вы обнаруживаете еще одну важную вещь: resolve
не прерывает выполнение кода. Несмотря на то, что данные возвращаются пользователю, вы все еще можете что-то сделать.
Или то же самое с await
let getSomeDataFromDB = async function(){
let conn = await reateConnection([skip])
let rows = await conn.query("SELECT 1 as val")
await conn.close();
return rows;
}
let rows = await getSomeDataFromDB()
Комментарии:
1. К сожалению, ни одно из вышеперечисленных решений не исправит мой код, потому что у меня довольно вложенные функции. Я попытаюсь перестроить весь код основного движка приложения, но большое вам спасибо за объяснение. Теперь я более или менее знаю, как его перехватить. Если кто-нибудь знает какое-либо необычное решение из приведенной выше ситуации, я буду благодарен.
2. @Dave Знаешь, ты задал общий вопрос, значит, у тебя есть общий ответ. Было бы неплохо знать, например: какую версию узла вы должны использовать. Я надеюсь, что обновленный ответ немного прояснил ситуацию. Если нет, вставьте фрагмент кода, который вы не понимаете. Если вы свяжетесь со мной, я попытаюсь объяснить, что там происходит.