1

I found a lot of question here related to it, but I can't figure out how to solve my specific problem.

I have a function that gets email users and send them an email. After each email sent, I add the respective user id in an array. Now I'm implementing the logger, so I need to save in the log the quantity of emails that were sent, to do that I just need to get the array length.

The problem is that is async, how can I get the array length only after sending the emails to all users?

async function asyncForEach(array, callback) {
    for (let index = 0; index < array.length; index++) {
        await callback(array[index], index, array);
    }
}

const waitFor = (ms) => new Promise(r => setTimeout(r, ms));

var sentMail = [];

module.exports = {
    sendReminderMail: function(db, mail, consts){                
            db.find({ $and: [{ subscribed: true }] }, { $not: { feedback: true } }] }, async (err, result) => {        
                if (err) {                    
                    logger.error(`${err.status || 500} - ${err} - '/sendReminderMail' - 'Schedule'`);
                } else {
                    await asyncForEach(result, async (subscriber, index) => {
                        await waitFor(2000 * index);                         
                        if (sentMail.indexOf(subscriber._id) < 0) {
                            mail.sendMail(subscriber, consts.emailType.REMINDER);                       
                            sentMail.push(subscriber._id);                                
                        }
                    });            
                }
            });
     }

}

I tried that, but in this case, the logger is called after each interation:

const waitFor = (ms) => new Promise(r => setTimeout(r, ms)).then(
logger.info(sentMail.length + 'mails was sent'));

Suppose that my sentMail array is this [123, 987,2545], so my logger should save 3 mails were sent.

ilkerkaran
  • 4,214
  • 3
  • 27
  • 42
mr.abdo
  • 445
  • 1
  • 5
  • 15
  • 2
    If you're writing a logger, it might be more sensible to write one log entry every time a single email is sent, instead of writing a single entry for multiple emails. Whatever consumers the log should be able to increment a counter just fine while parsing your log. – Mike 'Pomax' Kamermans Apr 23 '19 at 15:02
  • @Mike'Pomax'Kamermans, I have to save each mail sent as u said, and the total of emails that was sent in the end. – mr.abdo Apr 23 '19 at 15:06
  • Just place the logger statement after the `await asyncForEach(…)` loop? – Bergi Apr 23 '19 at 15:08
  • why do you need the total number of emails though? Your log parser can tell you that just fine without having to explicitly log that number, all it has to do is count the number of "email-send" log messages in a batch of log statements? – Mike 'Pomax' Kamermans Apr 23 '19 at 15:56

1 Answers1

0

You could easily return the count from that function.

return new Promise(resolve => {
            let emailCount = 0;
            db.find({ $and: [{ subscribed: true }] }, { $not: { feedback: true } }] }, async (err, result) => {        
            if (err) {                    
                logger.error(`${err.status || 500} - ${err} - '/sendReminderMail' - 'Schedule'`);
            } else {
                await asyncForEach(result, async (subscriber, index) => {
                    await waitFor(2000 * index);                         
                    if (sentMail.indexOf(subscriber._id) < 0) {
                        mail.sendMail(subscriber, consts.emailType.REMINDER);                       
                        sentMail.push(subscriber._id);
                        emailCount++                                
                    }
                });  
                resolve(emailCount);
            }
        });
 }
Sam Curry
  • 445
  • 2
  • 11
  • I apologize if I butchered the brackets there, it was hard for me to tell without highlighting. – Sam Curry Apr 23 '19 at 15:07
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Apr 23 '19 at 15:09