3

I'm new to async/await.

I'm trying to use async and await but the query is not waiting and it happens at last and the page renders before the query so I can't get the correct answer on rendered page.

Here is my code before using 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 })
            }
        })
}

However this doesn't work properly. console.log(total) happens before the query so the result is zero and it renders zero in the rendered page. Same thing happens if I use async. Am I using it wrong?

After using async await-

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 })
            }
        })
}

I tried without using callbacks like:

var A=  c.query('select * from cart where user_id=:userId',
        { userId: req.user.ID })

but then how can I get the output of the query? console.log(A) shows different results.

JohnReese
  • 103
  • 2
  • 6

3 Answers3

4

You can't because the functions don't return promises. You can promisify those function using a thirty-part library (for example es6-promisify) or you can wrap those by yourself.

Once a function returns a Promise, you can await it.

For example, for the above, a solution could be the following:

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);
  }
};
Egidio Caprino
  • 553
  • 10
  • 18
1

Assuming you're using the node-mariasql package. Short answer is you can't use async/await because the package does not support Promises.

Cisco
  • 20,972
  • 5
  • 38
  • 60
0

With node-mariasql it's easy to use 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 })
Teemu
  • 1