daniel aagentah
daniel aagentah

Reputation: 1702

res.render ONLY after multiple data queries have finished

On my app.get in my server.js, I am returning a data set from mongo db, and then rendering my page whilst passing the data to it.

as shown bellow:

//page load
app.get('/', (req, res) => {

    //find all data in test table
    var articles;
    db.collection('test').find().toArray((err, result) => {
        if (err) return console.log(err)
        articles = result

            // renders index.ejs and passes result to quotes
        res.render('./pages/index.ejs', {
            quotes: articles
        })
    })
})

I want to be able to put multiple db queries, and then pass multiple variables of data to my render, my problem is that when I put my res.render outside of a db query, it tries to render before the db gets its data set.

see what I tried bellow:

//page load
app.get('/', (req, res) => {

    //find all data in test table
    var articles;
    db.collection('test').find().toArray((err, result) => {
        if (err) return console.log(err)
        articles = result
    })

        // renders index.ejs and passes result to quotes
        res.render('./pages/index.ejs', {
            quotes: articles
        })
})

my question is:

How could I make sure that the render happens ONLY after my db queries have run and returned the data to a variable?


Ultimately I would want to be able to do something like this:

//page load
app.get('/', (req, res) => {

    //find all data in table 1
    var AAA;
    db.collection('test1').find().toArray((err, result) => {
        if (err) return console.log(err)
        AAA = result
    })

     //find all data in table 2
    var BBB;
    db.collection('test2').find().toArray((err, result) => {
        if (err) return console.log(err)
        BBB = result
    })

     //find all data in table 3
    var CCC;
    db.collection('test3').find().toArray((err, result) => {
        if (err) return console.log(err)
        CCC = result
    })

        // renders index.ejs and passes result to quotes
        res.render('./pages/index.ejs', {
            quotes: AAA,
            quotes2: BBB,
            quotes3: CCC
        })
})

Any help or advice on this is appreciated. Thank you in advance.

Upvotes: 1

Views: 2911

Answers (2)

jstice4all
jstice4all

Reputation: 1948

Try this code, it's not tested but I think it should work:

app.get('/', (req, res) => {

    var list = {};

    db.collection('test').find().toArray().then(result => {
        list.result = result;
    }).then(() => {
        return Promise.resolve(db.collection('foo').find().toArray());
    }).then(result2 => {
        list.result2 = result2;
    }).then(() => {
        return Promise.resolve(db.collection('bar').find().toArray());
    }).then(result3 => {
        list.result3 = result3;
    }).then(() => {
        res.render('./pages/index.ejs', list);
    }).catch(e => {
        console.error(e);
    });

});

Update: we can use async/await for any method that returns Promise so the code would be cleaner:

// you can use express-async-errors package to make routes async
app.get('/', async(req, res) => {
    let list = {};
    list.result = await db.collection('test').find().toArray();
    list.result2 = await db.collection('foo').find().toArray();
    list.result3 = await db.collection('bar').find().toArray();
    res.render('./pages/index.ejs', list);
});

Upvotes: 3

Bhavana
Bhavana

Reputation: 1054

You can use async module for that. Use async.parallel for functions which are independant of each other and use async.series for dependent processes. Check async.

Upvotes: 2

Related Questions