0

I have a route in my NodeJs app which takes a post request and then retrieves some data with await. The first await in my function works fine but then it complains when i call another function with await. I marked the function which causes the issue with >>>>

SyntaxError: await is only valid in async function

Has this error to do with the forEach Loop and if so how can i fix that

farmRoutes.post('/bulkemail/:farmid', async(req, res) => {

        try{
            const farmid = req.params.farmid
            // Check if we have an Emails Array
            if (typeof  req.body.emails != 'undefined' && req.body.emails instanceof Array ){
                // Assign Emails Array from Body to emails
                const emails = req.body.emails
                // get the current Emails Array from Farm Doc
               let oldEmail = await couch.getSubDoc('contacts', farmid ,'emails')

               // Loop thru all emails in the new Array
               emails.forEach((email) => {
                    console.log(email)
                    // Check if the email is curently already in the Farm Doc
                    var data = _.find(oldEmail, function(emailItem){ return emailItem.address == email; });
                    var index =_.indexOf(oldEmail,data);

                    if (index > -1) {
                        // Email already Exists will not be created
                        console.log("Email already in the List")
                    } else {
                        // if not in current Farm create new Email object and add to the oldEmail Array
                   >>>>>var newEmail = await contact.simp_email(simp_email)
                         // Upsert the updated Email Arra to farm Doc
                        var success = await cb.insertArrayItem(req.bucket, farmid, "emails", newEmail )
                        console.log(success)
                    }
               })
            } else {
                console.log("we have no new emails")
            }
NoSoup4you
  • 640
  • 1
  • 10
  • 34
  • Put async after before clouser function of emails.forEach(). As they are working in inner score. I.e emails.forEach(async (email) {}) – Sachin Kumar Apr 09 '20 at 19:15
  • Your `await` is in the callback function of `forEach`, not in the callback function of `post`. – Dave Newton Apr 09 '20 at 19:16

1 Answers1

2

Every function that awaits, must be an async function. Including the one passed to forEach.

emails.forEach(async (email) => {

Alternatively, you could avoid creating an iteration function by using a simple for of loop. This is usually preferred to using the forEach since it's a bit simpler and doesn't create any new functions.

for (const email of emails) {
    //...
    var newEmail = await contact.simp_email(simp_email)
    //...
}
Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
  • As I mentioned in my comment. – Sachin Kumar Apr 09 '20 at 19:17
  • So basically forEach is a new function and needs the async vs the for will not be a new function and allow await without the async. Is there any other major differences ? Also in your sample you said const email is that also the case if the email is an object ? – NoSoup4you Apr 09 '20 at 19:25
  • Correct. `for (const item of items)` is the [standard way](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) to write this loop and ensures you can't do `item = somethingElse` in the loop (this is good). What kind of data the array contains doesn't matter. `forEach` and `for of` do generally the same thing, but have some differences when it comes to iterators/generators which are advanced topics. Don't worry too much about those. But both let you execute some code each item in a list, which is what you care about here. – Alex Wayne Apr 09 '20 at 19:31
  • An interesting thing i found out just now is that if i call emails.forEach(async (email) => { it stops to execute some of the code synchronously vs with for (const email of emails) { it works as expected. In my case in the forEach case i returned the response before all code was executed. changing to the for it work fine – NoSoup4you Apr 09 '20 at 21:47
  • Which is why `for of` is recommended. Less gotchas. See also: https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop – Alex Wayne Apr 09 '20 at 21:49