0

I am working on an email web app where I try to replace certain keywords (first name, last name, email) with the actual properties of the user. Currently, I am looping through a list of recipients and editing the email content to be personalized with keywords replaced.

My issue: The forEach loop jumps past the promise used before I can use the regex expression to replace the keywords. How can I pause the loop to ensure all keywords are replaced before proceeding to the next iteration?

recipientList.forEach(function (recipient) {

        let setContent = new Promise((resolve,reject) =>{

                        personalizedContent = replaceAll(emailContent, '[First Name]', firstName);

                        personalizedContent = replaceAll(emailContent, '[Last Name]', lastName);

                        personalizedContent = replaceAll(emailContent, '[Email]', recipient.EmailAddress.Address);

                        resolve(personalizedContent);
                    })

       setContent.then((personalizedContent)=>{
            var message = {
                "Message": {
                    "Subject": subject,
                    "Body": {
                        "ContentType": "html",
                        "Content": personalizedContent
                    },
                    "ToRecipients": [recipient],
                    "Attachments": []
                },
                "SaveToSentItems": "true"
            };
            postEmail(accessToken,message);
        })



    });
Mohammed B
  • 305
  • 1
  • 4
  • 14
  • Read [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Satpal Jun 18 '19 at 06:04
  • Why is `setContent` a promise at all? Regex replacements are not asynchronous. Notice that you also overwrite `personalizedContent` twice – Bergi Jun 18 '19 at 08:49
  • well how do I get async behavior? I am trying to have the variable set prior to the loop executing – Mohammed B Jun 18 '19 at 14:08

2 Answers2

1

Since replaceAll isn't an async operation, you could just remove the usage of Promises and your code will work in the synchronous manner it is supposed to

 recipientList.forEach(function (recipient) {

      let personalizedContent = replaceAll(emailContent, '[First Name]', firstName);
      personalizedContent = replaceAll(emailContent, '[Last Name]', lastName);
      personalizedContent = replaceAll(emailContent, '[Email]', recipient.EmailAddress.Address);
        var message = {
            "Message": {
                "Subject": subject,
                "Body": {
                    "ContentType": "html",
                    "Content": personalizedContent
                },
                "ToRecipients": [recipient],
                "Attachments": []
            },
            "SaveToSentItems": "true"
        };
        postEmail(accessToken,message);
});
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • 2
    @Satpal, If replaceAll was async, the OP wouldn't be syncronously resolving the promise directly with `resolve` instead would wait for the replaceAll action to complete and have a .then or an async await for it – Shubham Khatri Jun 18 '19 at 06:18
0

I think it should be other way around. Try iterating recipient list inside promise and replace all the contents, then in the call back iterate the list again to update the message in post email.

Sasi Kumar M
  • 2,440
  • 1
  • 23
  • 23