Skip to content
Advertisement

How to execute multiple mongoose queries asynchronously and wait until all of them finish executing before sending response?

Thanks in advance, but could someone explain to me how can I execute a different query for each property of my request? I am trying to create a search sidebar menu, when user changes checkbox values I create an object with these properties:

    {
      "category": [
        "electronics",
        "clothing",
        "pets"
      ],
      "condition": [
        "old",
        "new"
      ]
    }

I want to push a query into an array of functions and then execute them using async.parallel When called i want to push the result of each query inside one array containing the result of all queries.

router.get('', async function(req,res)
{
    var searchResults = [];
    if(req.query.filters)
    {

        const queryObj = JSON.parse(req.query.filters);
        var searchQueries = [];
        if(queryObj.category){
            searchQueries.push(async function (cb) {
                return await Rentals.find({/* SOME CONDITION */}).populate('-something').exec(function (err, docs) {
                    if (err) {
                        throw cb(err);
                    }

                    cb(null, docs);
                });
            })    
        }

        if(queryObj.condition){
            searchQueries.push(async function (cb) {
                return await Rentals.find({/* SOME CONDITION */}).populate('-something').exec(function (err, docs) {
                    if (err) {
                        throw cb(err);
                    }

                    cb(null, docs);
                });
            })    
        }


        async.parallel(searchQueries, function(err, foundRentals) {
            if (err) {
                throw err;
            }
            searchResults.push(foundRentals[0]); // result of searchQueries[0]
            searchResults.push(foundRentals[1]); // result of searchQueries[1]
            searchResults.push(foundRentals[2]); // result of searchQueries[2]

        })
    }
    res.json(searchResults);
});

The problem comes when returning searchResults, I am receiving an empty array from the server however after the response was sent the queries finish and I get the result AFTER response was sent. How can I execute all queries at the same time and wait until all of them finish before sending a response to client?

Advertisement

Answer

Your promise.all code version would look something like this:

router.get('', async function(req,res)
{
    try{
        let searchResults = [],
            categoryPromises = [],
            conditionPromises = [];

        if(req.query.filters)
        {

            const queryObj = JSON.parse(req.query.filters);
            if(queryObj.category && queryObj.category.length > 0){
                categoryPromises = queryObj.category.map(singleCategory=>{
                    return Rentals
                        .find({/* SOME CATEGORY? */})
                        .populate('-something')
                        .exec();
                });   
            }

            if(queryObj.condition && queryObj.condition.length > 0){
                conditionPromises = queryObj.category.map(singleCondition=>{
                    return Rentals
                        .find({/* SOME CONDITION */})
                        .populate('-something')
                        .exec();
                });   
            }

            searchResults.push(await categoryPromises);
            searchResults.push(await conditionPromises);

        }
        res.json(searchResults);
    }catch(e){
        // catch-all error handling here
    }
});

(instead of .map you could also use a for-loop to push them into a categoryPromises array)

Advertisement