Как правильно использовать асинхронное ожидание с запросом 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 })
Другие вопросы по тегам