Reputation: 197
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?
Upvotes: 0
Views: 1311
Reputation: 197
I solved it using this syntaxis
let finalResults = await Promise.all(arrayToIterate.map(async(value) => { // map instead of forEach
const result = await getRentalsByQuery({query});
finalValue = result;
return finalValue; // important to return the value
}));
Upvotes: 1
Reputation: 8617
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)
Upvotes: 1