Как правильно использовать асинхронное ожидание с запросом mariadb в NodeJs?
Я новичок в асинхронных / жду.
Я пытаюсь использовать async и await, но запрос не ждет, и, наконец, это происходит, и страница отображается перед запросом, поэтому я не могу получить правильный ответ на отображаемой странице.
Вот мой код перед использованием асинхронного ожидания
orderMiddleware.newOrder = function (req, res) {
var total = 0
var curr_total = 0
// get items from cart
c.query('select * from cart where user_id=:userId',
{ userId: req.user.ID }, function (err, cart) {
if (err) {
console.log(err)
} else {
cart.forEach(function (item) {
// Find item from DB and check their price
c.query('select * from products where id=:id',
{ id: item.item_id },
function (err, foundItem) {
if (err) {
console.log(err)
} else {
curr_total = foundItem[0].price * item.quantity
console.log("currenttotal" + curr_total)
total += curr_total
console.log(total)
}
})
})
console.log(total)
console.log(curr_total)
// Calculate total price
// Multiply all items with their quantity
res.render('orders/new', { cart: cart, total: total })
}
})
}
Однако это не работает должным образом. console.log(total) происходит перед запросом, поэтому результат равен нулю, и он отображает ноль на отображаемой странице. То же самое происходит, если я использую async. Я использую это неправильно?
После использования асинхронного ожидания
orderMiddleware.newOrder = async (req, res) => {
var total = 0
var curr_total = 0
// get items from cart
var A= c.query('select * from cart where user_id=:userId',
{ userId: req.user.ID }, async (err, cart) => {
if (err) {
console.log(err)
} else {
cart.forEach(async (item) => {
// Find item from DB and check their price
await c.query('select * from products where id=:id',
{ id: item.item_id },
async (err, foundItem) =>{
if (err) {
console.log(err)
} else {
curr_total = foundItem[0].price * item.quantity
console.log("currenttotal" + curr_total)
total += curr_total
console.log(total)
}
})
})
await console.log(total)
// await console.log(curr_total)
// Calculate total price
// Multiply all items with their quantity
await res.render('orders/new', { cart: cart, total: total })
}
})
}
Я пытался без использования обратных вызовов, таких как:
var A= c.query('select * from cart where user_id=:userId',
{ userId: req.user.ID })
но тогда как я могу получить результат запроса? console.log(A) показывает разные результаты.
2 ответа
Вы не можете, потому что функции не возвращают обещания. Вы можете обещать эти функции, используя библиотеку из тридцати частей (например, es6-promisify), или вы можете обернуть их самостоятельно.
Как только функция возвращает обещание, вы можете его дождаться.
Например, для вышеизложенного, решение может быть следующим:
const execQuery = (sql, params) => new Promise((resolve, reject) => {
query(sql, params, (error, data) => {
if (error) {
reject(error);
} else {
resolve(data);
}
});
});
const logCartItem = async (userId) => {
try {
const items = await execQuery('select * from cart where user_id=:userId', { userId });
items.forEach(console.log);
} catch (error) {
console.error(error);
}
};
Предполагая, что вы используете node-mariasql
пакет. Короткий ответ: вы не можете использовать async/await
потому что пакет не поддерживает обещания.
С node-mariasql легко использовать promisify
const util = require('util')
const asyncQuery = util.promisify(c.query);
const rows = await asyncQuery.call(c, 'SELECT product FROM products WHERE id = :id', { id }, { useArray: false, metaData: false })