kinkajou
kinkajou

Reputation: 99

NodeJS problem getting multiple query results simultaneously?

It's my first project using NodeJS, and I'm trying to fetch all posts in all groups in which the user is a member. And as such, I'm trying to put all the data into and array before calling the res.send method. However, the array is empty at the end (pardon the naming of tables as I used french).

router.get('/getUserPostes/:userId', async (req, res) => {
    let userId = req.params.userId;
    let endResult = []
    await db.query('select groupeId from groupemembers where userId = ?', userId, async function(err, result){
        if (err){
            console.log(err.message)
            res.send(null)
        }
        else {
            await result.map(async groupe => {
                await db.query('select * from postes where groupeId = ?', groupe.groupeId, function(err, result){
                    if (result != []){
                        endResult.push(result)
                    }
                })
            })
            res.send(endResult)
        }
    })
})

Upvotes: 0

Views: 754

Answers (2)

jfriend00
jfriend00

Reputation: 708146

await result.map() does not do what you want because you're awaiting an array (since .map() return an array) not a promise. You could do await Promise.all(result.map(...)) or change to a for loop and await each individual request.

Also, await db.query() also does not do anything useful because you're also passing a callback. If you pass a callback, then it does NOT return a promise. Please don't just go cramming an await everywhere without understanding how you're precisely awaiting a promise since that's the only thing it is useful to await.

And, if this is mysql, then you will want a nodejs driver for mysql that supports promises so you can do it this way:

router.get('/getUserPostes/:userId', async (req, res) => {
    const userId = req.params.userId;
    try {
        const endResult = [];
        const result = await db.query('select groupeId from groupemembers where userId = ?', userId);
        for (const groupe of result) {
            let groupResult = await db.query('select * from postes where groupeId = ?', groupe.groupeId);
            if (groupResult) {
                endResult.push(groupResult);
            }
        }
        res.send(endResult);
    } catch (e) {
        console.log(err);
        res.sendStatus(500);
    }
});

To use promises with mysql, there are a number of ways to get promise support. One such way is to use the mysql2 module and do this:

const mysql = require('mysql2/promise');

Upvotes: 1

Dom
Dom

Reputation: 157

The function .map is not an asynchronous function so you are essentially sending you're response before the queries within .map are complete. Assuming your DB library supports promises, something like this would be more clean:

router.get('/getUserPostes/:userId', async (req, res) => {
  let userId = req.params.userId;
  try {
    const result = await db.query('select groupeId from groupemembers where userId = ?', userId)

    const endResult = await Promise.all(result.map(groupe => {
      return db.query('select * from postes where groupeId = ?', groupe.groupeId)
    }))
    res.send(endResult)
  } catch (err) {
    console.log(err.message)
  }
})

Bear in mind that there is likely a single query that you can pull this data with. However, without knowing the DB schema, it would be difficult for me to help with this.

Upvotes: 1

Related Questions