These are chat archives for Automattic/mongoose

27th
Nov 2017
Shaad Khan
@shaad-khan
Nov 27 2017 10:30
please help me with asyn callback with below code:
router.get('/:client',function(req,res){
var dict = [];
//console.log("hey there");

Appcheck.count({'Client':req.params.client,Flag:1}, function(err, data) {
if (err) throw err;


// console.log(data);

dict.push({error:data})


});
Appcheck.count({'Client':req.params.client}, function(err, data) {
if (err) throw err;


// console.log(data);

dict.push({total:data})

});
Appcheck.count({'Client':req.params.client,Flag:0}, function(err, data) {
if (err) throw err;


// console.log(data);

dict.push({Success:data})
//res.json(dict);    /* here its returning the values  as json response but one at a time as its asyn call */
});

res.json(dict);  /* here its returning empty json */
});
Paul "Joey" Clark
@joeytwiddle
Nov 27 2017 10:47

@shaad-khan You cannot read dict at the top level. You have to do your final action inside the last callback. In fact all your callbacks need to be nested, like this:

router.get('/:client',function(req,res){
    var dict = [];
    Appcheck.count({'Client':req.params.client,Flag:1}, function(err, data) {
        if (err) throw err;
        dict.push({error:data})
        Appcheck.count({'Client':req.params.client}, function(err, data) {
            if (err) throw err;
            dict.push({total:data})
            Appcheck.count({'Client':req.params.client,Flag:0}, function(err, data) {
                if (err) throw err;
                dict.push({Success:data})
                res.json(dict);    /* here its returning the values  as json response but one at a time as its asyn call */
            });
        });
    });
});

But you can do it more cleanly with promises:

router.get('/:client', async function(req, res, next) {
    var dict = [];
    Promise.resolve().then(() => {
        return Appcheck.count({'Client': req.params.client, Flag: 1});
    }).then(data1 => {
        dict.push({error: data1});
        return Appcheck.count({'Client': req.params.client});
    }).then(data2 => {
        dict.push({total: data2})
        return Appcheck.count({'Client': req.params.client, Flag: 0});
    }).then(data3 => {
        dict.push({Success: data3})
        res.json(dict);
    }).catch(error => {
        next(error);
    });
});

Or very cleanly with async-await:

router.get('/:client', async function(req, res, next) {
    try {
        var dict = [];
        const data1 = await Appcheck.count({'Client': req.params.client, Flag: 1});
        dict.push({error: data1});
        const data2 = await Appcheck.count({'Client': req.params.client});
        dict.push({total: data2})
        const data3 = await Appcheck.count({'Client': req.params.client, Flag: 0});
        dict.push({Success: data3})
        res.json(dict);
    } catch (error) {
        next(error);
    }
});
By the way, your throw err; should probably be return next(err);, so that express can handle the error, instead of crashing Node.
In the last two examples, you could also use Promise.all() if you wanted to run the queries in parallel.
Shaad Khan
@shaad-khan
Nov 27 2017 10:55
@joeytwiddle thanks for your help it worked. Can you please provide me an example for how to use Promise.all() for running parallel queries
Shaad Khan
@shaad-khan
Nov 27 2017 11:06
@joeytwiddle ok sorry i missed the first part got it now actually got confused a bit thanks for your help
Paul "Joey" Clark
@joeytwiddle
Nov 27 2017 13:24

@shaad-khan

Promise.all([Appcheck1(), Appcheck2(), Appcheck3()]).then(([data1, data2, data3]) => {
    // ...
}).catch(next);

or

const [data1, data2, data3] = await Promise.all([Appcheck1(), Appcheck2(), Appcheck3()]);