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")
            }
2
  • Put async after before clouser function of emails.forEach(). As they are working in inner score. I.e emails.forEach(async (email) {}) Commented Apr 9, 2020 at 19:15
  • Your await is in the callback function of forEach, not in the callback function of post. Commented Apr 9, 2020 at 19:16

1 Answer 1

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)
    //...
}
Sign up to request clarification or add additional context in comments.

5 Comments

As I mentioned in my comment.
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 ?
Correct. for (const item of items) is the standard way 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.
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
Which is why for of is recommended. Less gotchas. See also: stackoverflow.com/questions/37576685/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.