简体   繁体   中英

using express to loop through a mongoose schema function ,collecting data into an array and rendering the page finally with all the data

Nodejs +Express+Mongoose beginner's question:

*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 *

My express code explains my agony better. Please have a look:

//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);
});
}

Just for the record

Everything is working great, I am just having trouble rendering my page because the menFashion and womenFashion array aren't accesible outside the callback.

A thanks in advance :)

UPDATE:

I solved it myself,but still thnks guys (specially @faiz)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM