3

I have a NodeJS API using Express 4. I am using sequelize to connect to the database and I invoke one query many times. I want accumulate the results into an Array. The problem is that res.send doesn't wait for the loop to end to send the answer.

my code

router.post('/payrollReport/', function(req, res, next) {
    var usersRecord = [];
    models.user.findAll(
    ).then(function(users) {
      for (var i = 0; i < users.length; i++) {
            models.sequelize.query('SELECT forms.name, COUNT(form_submits.form_id)  ' +
                    'FROM form_submits ' + 
                    'LEFT JOIN forms ON forms.form_id = form_submits.form_id ' +
                    'WHERE form_submits.user_id = ' + users[i].user_id +
                    'AND date("form_submits"."createdAt") >=' + req.body.begin +
                    'AND date("form_submits"."createdAt") <=' + req.body.end +
                    " GROUP BY forms.name")
             .then(function(results){
                 usersRecord.push(results[0]);
                 console.log(usersRecord);
            });      
      };
    }).catch(function(error) {
      res.status(500).send(error);
    });  
    res.send(usersRecord);
});

thanks for your help

EDIT

Add the correct code using forEach

router.post('/payrollReport/', function(req, res, next) {
    var usersRecord = [];
    models.user.findAll(
    ).then(function(users) {
       async.forEachOf(users, function iterator(user, index, callback) {
            models.sequelize.query('SELECT forms.name, COUNT(form_submits.form_id)  ' +
                    'FROM form_submits ' + 
                    'LEFT JOIN forms ON forms.form_id = form_submits.form_id ' +
                    'WHERE form_submits.user_id = ' + user.user_id +
                    'AND date("form_submits"."createdAt") >=' + req.body.begin +
                    'AND date("form_submits"."createdAt") <=' + req.body.end +
                    " GROUP BY forms.name")
             .then(function(results){
                 results[0].unshift(user); 
                 usersRecord.push(results[0]);
                 callback();
            });   

         }, function (err) {
          if (err) console.error(err.message);
          res.send(usersRecord);
       });


    }).catch(function(error) {
      res.status(500).send(error);
    });  

});
oriaj
  • 768
  • 1
  • 16
  • 33
  • Soooo... your question is what? You will likely need to store all you promisables into an array and use the `Promise.all` method, as to act only when all of your promises have been resolved. – An0nC0d3r Jan 04 '16 at 17:03
  • you should chain your `.then()`'s and not have one inside another. – Craicerjack Jan 04 '16 at 17:05
  • 3
    You want `Promise.all(users.map(...))`. Read http://blog.slaks.net/2015-06-10/advanced-promise-usage/ – SLaks Jan 04 '16 at 17:06

1 Answers1

5

Since node.js works asynchronously, your res.send(usersRecord); command is executed before all iterations are done. You can use async.foreach for this, it will allow you to run your send only after all iterations are done.

There's a great tutorial about it here

Nir Levy
  • 12,750
  • 3
  • 21
  • 38