*So I came across this problem where I had an array of categories (clothes category). For each category, I wanted to fetch results from the database. So I did what a normal person would do. I used a for loop, fetched the product, stored in an array, then fetched next product, stored in into the same array and so on....... (same process for men and women both ). Now i want to render my view with the data but it isn't accessible coz of the asynchronous nature of node js. I totally understand it. So what I am looking for is an alternative/solution for my problem *
//INDEX PAGE
router.get('/', (req, res, next) => { //anonymous callback function
let allCategories;
let womenFashion = [],
menFashion = [];
Clothing.groupByBodyPart(function(err, categories) {
if (categories) {
allCategories = categories.slice(0);
for (let i = 0; i < allCategories.length; i++) { //looping
let category = allCategories[i]._id; //gives a category, eg.,footwear,bottomwear
Clothing.getCategoryWise(category, 'M', function(err, products) { //products here will be an array of objects
if (products) {
menFashion[i] = products.slice(0); //storing products into an array for future use
console.log(menFashion[i]); //accessible here one at a time Eg.,[{slippers},{shoes}]
}
});
Clothing.getCategoryWise(category, 'F', function(err, products) {
if (products) {
womenFashion[i] = products.slice(0); //same as above
console.log(womenFashion[i]); //same as above
}
});
}
}
console.log(menFashion[0]); // not accessible here, so I can't render my page
res.render('index.pug', {
allCategories,
menFashion,
womenFashion
}); //won't work as menFashion and womenFashion aren't available
});
});
Here you go with the mongoose static function:
//get categorywise products
clothingSchema.statics.getCategoryWise = function(bodyPart,gender,callback){
Clothing.aggregate([
{ $match: {'category.bodyPart': bodyPart,
'category.gender': gender
}
},
{ $group: {_id: "$category.type" }
},
{ $sort: {_id: 1 }
}
])
.exec((err,products)=>{
if(err){
return callback(err);
}else if(!products){
let err = new Error('No Product Found!');
err.status = 401;
return callback(err);
}
return callback(null,products);
});
}
Everything is working great, I am just having trouble rendering my page because the menFashion and womenFashion array aren't accesible outside the callback.
My solution basically includes nesting:
//INDEX PAGE
router.get('/',(req,res,next)=>{ //anonymous callback function
let allCategories;
let womenFashion = [], menFashion = [];
Clothing.groupByBodyPart(function(err,categories){
if(categories){
allCategories = categories.slice(0);
for(let i = 0; i < allCategories.length; i++){ //looping
let category = allCategories[i]._id; //gives a category, eg.,footwear,bottomwear
Clothing.getCategoryWise(category,'M',function(err,products){ //products here will be an array of objects
if(products){
menFashion.push(products);
menFashion[i] = products.slice(0); //storing products into an array for future use
//console.log(menFashion[i]); //accessible here on at a time Eg.,[{slippers},{shoes}]
}
Clothing.getCategoryWise(category,'F',function(err,products){
if(products){
womenFashion[i] = products.slice(0); //same as above
//console.log(womenFashion[i]); //same as above
}
if(i == allCategories.length-1){
console.log('men',menFashion); //everything accessible
console.log('men',menFashion); //everything accessible
res.render('index.pug',{allCategories,menFashion,womenFashion}); //tadaaaaaaaa
}
});
});
}
}
});
});
You can use something like this.
I used two Promise.all
calls to make sure that you have two results that you can use. You can just as well use one Promise.all
router.get('/', (req, res, next) => { //anonymous callback function
let allCategories;
let womenFashion = [],
menFashion = [];
Clothing.groupByBodyPart(function (err, categories) {
if (categories) {
allCategories = categories.slice(0);
const menPromises = [];
const womenPromises = [];
for (let i = 0; i < allCategories.length; i++) { //looping
let category = allCategories[i]._id; //gives a category, eg.,footwear,bottomwear
menPromises.push(
new Promise((resolve, reject) => {
Clothing.getCategoryWise(category, 'M', function (err, products) { //products here will be an array of objects
if (products) {
menFashion[i] = products.slice(0); //storing products into an array for future use
resolve(menFashion[i]);
console.log(menFashion[i]); //accessible here one at a time Eg.,[{slippers},{shoes}]
}
})
})
);
womenPromises.push(
new Promise((resolve, reject) => {
Clothing.getCategoryWise(category, 'F', function (err, products) { //products here will be an array of objects
if (products) {
womenFashion[i] = products.slice(0); //storing products into an array for future use
resolve(womenFashion[i]);
console.log(womenFashion[i]); //accessible here one at a time Eg.,[{slippers},{shoes}]
}
})
})
);
}
Promise.all([Promise.all(menPromises), Promise.all(womenPromises)]).then(([menResults, womenResults]) => {
console.log(menFashion[0]); // not accessible here, so I can't render my page
res.render('index.pug', {
allCategories,
menFashion,
womenFashion
}); //won't work as menFashion and womenFashion aren't available
});
}
});
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.