0

I am trying to get posts from database by using ID.So I am looping around an array of Id's and using mongoose method 'findById' to get response.But the loop finishes iterations before completing the body. How to deal with this?


function getSortedPosts(callback){
    var landingPosts = new Object;
    categoryModel.find((err,categories) => {
        if(err) console.log(err);
        else{
            categories.forEach((category,i) => {
                landingPosts[category.category] = new Array;
                //for each post in  a category
                category.posts.forEach((postid,j) => {
                    console.log(":")
                    //limiting posts per category to 3
                    if (j<3){
                        postModel.findById(postid,(err,foundpost) => {
                            if(err) console.log(err)
                            else{
                                landingPosts[category.category].push(foundpost);
                                if(i === categories.length-1){
                                    console.log(i)
                                    if(j === 2){
                                      callback(landingPosts);
                                    }
                                }
                            }
                        })
                    }
                })
            })
        }
    })
}
getSortedPosts((lp) => {.......})

I don't know how to use promises or async await...so I am using callbacks. Would learning them now help me with this? (I plan to learn them after present project as I am beginner and they confuse me)

Sasi Kanth
  • 55
  • 3
  • *"Would learning them now help me with this?"* Yes, but you'd need a wrapper for `findById`, which doesn't [seem to return a promise](https://mongoosejs.com/docs/api.html#model_Model.findById) (I find that odd, I thought they'd added promises to the API). – T.J. Crowder Jan 04 '20 at 12:50
  • Is it: A) Important that the operations run in *series* (one after another); B) Important that they run in *parallel* (all at once, overlapping); or C) Either way is fine ? – T.J. Crowder Jan 04 '20 at 12:51
  • [My answer here](https://stackoverflow.com/a/43766002/157247) shows how to do multiple async operations (with and without promises), but I hesitate to dupehammer this question as a duplicate of that one...though I suppose it is, really, by SO's definition. – T.J. Crowder Jan 04 '20 at 12:52
  • 1
    I want them to run in series. A). – Sasi Kanth Jan 04 '20 at 12:53
  • 1
    Side note about `var landingPosts = new Object;`: There's almost never any reason to use `new Object` instead of `{}`, like this: `var landingPosts = {};` – T.J. Crowder Jan 04 '20 at 12:53

2 Answers2

1

I would divide the functionalities in different functions which does only one job and then have another one which uses these function to get the final output. something like this

function findPostById(postId) {
  return new Promise((resolve, reject) => {
    postModel.findById(postid, (err, foundpost) => {
      if (err) {
        reject(err);
      } else {
        resolve(foundpost);
      }
    });
  });
}

function findCategories() {
  return new Promise((resolve, reject) => {
    categoryModel.find((err, categories) => {
      if (err) {
        reject(err);
      }
      resolve(categories);
    });
  });
}

async function getSortedPosts() {
  const categories = await findCategories();
  const landingPosts = {};
  for (const category of categories) {
    for (const post of category.posts) {
      const foundpost = await findById(post.postId);
      landingPosts[category.category].push(foundpost);
    }
  }
}

I haven't done the logic for limiting the number of posts but you get an idea, how to structure the code.

Hope this helps

Ashish Modi
  • 7,529
  • 2
  • 20
  • 35
1

You should definitely learn async await before even starting this project.

async function getSortedPosts() {
    var landingPosts = {};
    var categories = await categoryModel.find().catch(console.log);
    for(let item of categories) {
        let category = item.category;
        landingPosts[category] = [];

        for(let id of item.posts.slice(0,2)) {
            let post = await postModel.findById(id).catch(console.log);
            landingPosts[category].push(post);
        }
    }

    return landingPosts;
}

Call the getSortedPosts function like this -

getSortedPosts().then(landingPosts => {
    // some logic
})

I didn't run the code, but hope you can solve the errors.