These are chat archives for Automattic/mongoose

24th
Oct 2018
Hitesh Joshi
@evoxtorm
Oct 24 2018 04:22
router.validateData = function(req, res) {
    let data = req.body;
    let redudantData = [];
    for (let i = 1; i < data.length; i++) {
        let number = data[i][6].toString();
            User.aggregate([
                { $match: { contactNumber: number}},
                { $project: {
                    'name': 1,
                    'contactNumber': 1
                }}
            ]).exec(function(err, userData) {
                if (err) {
                    res.status(500).json(err);
                } else if (userData.length == 0) {
                    console.log("No old user found for this number ");
                    console.log(number);
                    redudantData.push(number);
                    console.log(redudantData);
                } else {
                    // userData.rowNo = i;
                    // redudantData.push(userData);
                    //console.log(redudantData);
                }
            })
    }
    if (data.length - 1 == i ) {
        res.status(200).send(redudantData);
    }    
}
Hey, My response is fired before the loop end
how I can send it after the loop is over
I've used async await but it is also not working I don't know where is the problem is
Thanks in advance
Ghost
@ghost~5b53da7dd73408ce4fa1d2e5
Oct 24 2018 07:42
Hi, why the next() function in the mongoose middleware for error handling need the error as an argument like next(err) ? Like this one
schema.pre('save', function(next) {
  const err = new Error('something went wrong');
  // If you call `next()` with an argument, that argument is assumed to be
  // an error.
  next(err);
});
Kev
@lineus
Oct 24 2018 09:40
@evoxtorm when you perform async operations in loops, the loop will most likely complete before all of the callbacks have finished. If you're on a very modern version of node ( e.g. > 10 ) you can use for - await - of, but the following solution ( or a close approximation ) should work if you're on an older version:

router.validateData = function(req, res) {
  let data = req.body;
  let redudantData = [];
  let promises = [];
  for (let i = 1; i < data.length; i++) {
    let number = data[i][6].toString();
    promises.push(
      User.aggregate([
        { $match: { contactNumber: number}},
        { $project: {
          'name': 1,
          'contactNumber': 1
        }}
      ]).then(function(userData) {
        if (userData.length == 0) {
          console.log('No old user found for this number ');
          console.log(number);
          redudantData.push(number);
          console.log(redudantData);
        } else {
          // userData.rowNo = i;
          // redudantData.push(userData);
          //console.log(redudantData);
        }
      }).catch(someErrorHandlingFunction)
    );
  }
  Promise.all(promises).then(() => {
    res.status(200).send(redudantData);
  });
};
Kev
@lineus
Oct 24 2018 13:46
@isemaj_gitlab you can also return a rejected promise or throw inside a hook if you would prefer. This gist is an example.
Andrés Da Viá
@adavia
Oct 24 2018 17:26
Im confused about querying for a list of products along its 5 first images for each product but the following query limit the number of images only in the first product. Not as expected...
Product.find().populate({path: 'images', options: {limit: 5}});