-3

I have an async function that waits for a promise:

const getUserByImportMail = async (mail) => {
  const mailResult = await client.request(GET_COMPANY_BY_IMPORT_MAIL, mail)

  console.log("In file 1: " + inspect(mailResult))

  return mailResult
}

and another function in another file which does some checks on it:

const isSenderValid = mail => {
  const importMail = getUserByImportMail({importMail: mail})

  console.log("In file 2: " + inspect(importMail))

  // some checks
  return importMail
}

I always thought that async functions will wait for the Promise to resolve which they do, kinda:

// In file 1: { companies: [{obj}] }

but

// In file 2: Promise { <pending> }

Why is execution continued for isSenderValid and not being wait for the Promise to resolve, and how to fix it?

supersize
  • 13,764
  • 18
  • 74
  • 133
  • because there is no await – enno.void Dec 11 '18 at 10:02
  • 2
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Keith Dec 11 '18 at 10:02
  • `async` functions always return a Promise - the keyword works like a kind of a wrapper for a function. – Szab Dec 11 '18 at 10:04

1 Answers1

3

Your getUserByImportMail function is async, that means it will return a Promise for whatever it finally returns as mailResult. You should make isSenderValid also an async function and then it can await the result of the call:

const isSenderValid = async mail => {
  const importMail = await getUserByImportMail({importMail: mail})

  console.log("In file 2: " + inspect(importMail))

  // some checks
  return importMail
}

Then of course whatever calls isSenderValid also has to use await and be an async function itself. All the way down.

Alternatively isSenderValid can use the Promise directly, but in that case it cannot return importMail. If you call a function that is async i.e. returns Promise then you cannot return anything that depends on the result of that Promise directly: everything else has to be async as well.

Here's how you could handle the Promise inside isSenderValid and return another Promise which will resolve to importMail:

const isSenderValid = mail => {
  return getUserByImportMail({importMail: mail})
  .then(importMail => {
      console.log("In file 2: " + inspect(importMail))

      // some checks
      return importMail
  });
}
Duncan
  • 92,073
  • 11
  • 122
  • 156
  • Thanks, can you elaborate on this statement: `Alternatively isSenderValid can use the Promise directly, but in that case it cannot return importMail`? – supersize Dec 11 '18 at 10:07
  • He means you can do -> `isSenderValid.then(result => ....)` Basically the callback version of Promises, and of course you can't return from a callback either. IOW: Once `async` always `async`, sound limiting, but in the long run it's a good thing.. :) – Keith Dec 11 '18 at 10:07
  • Sure, was just in the process of updating my answer to include the Promise example anyway. – Duncan Dec 11 '18 at 10:09
  • Very helpful. So essentially every function referencing a return value of a Promise will either need an await too or then. – supersize Dec 11 '18 at 10:11