Async must be declared on nearest function even if it is anonymous

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the javascript category.

Last Updated: 2021-05-15

I was using await deep in this code to wait for the return value of fetchHubspotDetails().

function getDeals() {
  var query = "select * from paypal_deals where dealId IS NULL and contactId != 0 limit 10"

  mysqlConnection.query(query, (error, result, fields) => {
    result.forEach(item => {
      var contactId = item.contactId
      // Here is `await`
      data = await fetchHubspotDetails(contactId)
    })
  })
}

However it failed with: SyntaxError: await is only valid in async function.

I tried fixing by putting async around the entire function:

// Async added here
async function getDeals() {
  var query = "select * from paypal_deals where dealId IS NULL and contactId != 0 limit 10"

  mysqlConnection.query(query, (error, result, fields) => {
    result.forEach(item => {
      var contactId = item.contactId
      data = await fetchHubspotDetails(contactId)
    })
  })
}

No dice.

The issue was that the fetchHubspotDetails was nested within an anonymous function and it was this anonymous function (not the outer function) that required the async modification:

// Get deals that need a customer

function getDeals() {
  var query = "select * from paypal_deals where dealId IS NULL and contactId != 0 limit 10"

  mysqlConnection.query(query, (error, result, fields) => {
    // Notice the `async` within with function passed to `forEach`
    result.forEach(async item => {
      var contactId = item.contactId
      data = await fetchHubspotDetails(contactId)
    })
  })
}

Lesson

Async must be declared on nearest function, even if that one is anonymous.