0

I am trying to show results of two SQL queries in one page. My code is in module.exports block and the whole application in written in Node.js Express. This returns an error "Cannot read property 'length' of undefined".

var message = "some random text";
var res_points, res_types;
    db.query(query, (err, result) => {
        if (err) {
            res.redirect('/');
        }
        res_points= result;
    });
    db.query(query2, (err, result) => {
        if(err) {
            res.redirect('/');
        }
        res_types = result;
    });

    res.render('index.ejs', {
        title: message,
        ,points: res_points
        ,types: res_types
    });

When I do it like this, it works:

db.query(query, (err, result) => {
        if (err) {
            res.redirect('/');
        }
        res.render('index.ejs', {
            title: message,
            points: result
        });
    });

What am I doing wrong? Or better said, how can I pass results of those two queries into the render function?

Ivanka Eldé
  • 228
  • 1
  • 2
  • 12
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Marcos Casagrande Nov 12 '18 at 19:48
  • @MarcosCasagrande This question is not about async call in Ajax, it's about finding a correct way how to send results of two queries in one response and why my code didn't worked as it was in Node. – Ivanka Eldé Nov 12 '18 at 19:54
  • It's about how to get the response from an async call, and use that response, if you really read that question and the answers, you will find yours in there. In any case since you posted a valid answer, I will give you a better approach. – Marcos Casagrande Nov 12 '18 at 19:57
  • Did you check my answer? – Marcos Casagrande Nov 19 '18 at 14:16

2 Answers2

1

I found a workaround like this, but I really don't think this is the only, corrent and elegant way how to do it:

    let res_points, res_types;
    db.query(query, (err, result) => {
        if (err) {
            res.redirect('/');
        }
        db.query(query2, (err2, result2) => {
            if(err2) {
                res.redirect('/');
            }
            res.render('index.ejs', {
                title: "Welcome to Hamburg Map | View Points"
                ,points: result
                ,types:result2
            });
        });
    });
Ivanka Eldé
  • 228
  • 1
  • 2
  • 12
1

The cleanest approach here is to use Promises & Promise.all. For that you will need to wrap db.query in a Promise.

// You can use Util.promisify too
const queryWrapper = (statement) => {

    return new Promise((resolve, reject) => {

        db.query(statement, (err, result) => {
            if(err)
                return reject(err);

            resolve(result);
        });

    });

};


app.get('/some-route', (req, res, next) => {
    const message = "some random text";

    Promise.all([
        queryWrapper(query),
        queryWrapper(query2)
    ])
    .then(([points, types]) => {

        res.render('index.ejs', {
            title: message,
            points,
            types
        });
    })
    .catch(err => {
        console.error(err);
        res.redirect('/');
    })
});

Note: If you're using MySQL, the mysql2 package offers promise support, so you can avoid the Promise wrapper.

Marcos Casagrande
  • 37,983
  • 8
  • 84
  • 98
  • yes thank you, this is really nice solution. What would change if I wanted to make two queries for different URLs? Let's say one for getting all types such as "/types?" and second for points of certain type "/points?type=1". – Ivanka Eldé Nov 20 '18 at 10:14
  • Just have two different routes. Copy and paste the express route, one will be for /types and the other for /points. – Marcos Casagrande Nov 20 '18 at 12:45