1

I am having a problem where an async function does not appear to be waiting. I am calling one async function from another, with the second returning a value after async operations have completed and then the first should be returning this as it has awaited it. But when logging accessToken in the first function it logs before awaiting the return from the second. Where am I going wrong? Thanks in advance.

export const confirmCode = async (verificationId, code) => {
  try {
    const credential = await firebase.auth.PhoneAuthProvider.credential(verificationId, code);
    const accessToken = await authenticate(credential);
    console.log(accessToken); // prints undefined as does not wait for above function call?
    return accessToken;
  } catch (error) {
    console.log(error)
    // this.showMessageErrorByCode(e.error.code);
  }
}

const authenticate = async (credential) => {
  try {
    await firebase.auth().signInWithCredential(credential).then(result => {
      const user = result.user;
      user.getIdToken().then(accessToken => {
        return accessToken;
      });
    })
  } catch (error) {
    console.log(error);
  }
}
Mr. Robot
  • 1,334
  • 6
  • 27
  • 79

1 Answers1

4

You should not mix async/await with the older version .then().

Just use it without then() like so:

export const confirmCode = async (verificationId, code) => {
  try {
    const credential = await firebase.auth.PhoneAuthProvider.credential(verificationId, code);
    const accessToken = await authenticate(credential);
    console.log(accessToken); // prints undefined as does not wait for above function call?
    return accessToken;
  } catch (error) {
    console.log(error)
    // this.showMessageErrorByCode(e.error.code);
  }
}

const authenticate = async (credential) => {
  try {
    let result = await firebase.auth().signInWithCredential(credential); // <-- use await
    const user = result.user;
    accessToken = await user.getIdToken(); // <-- use await
    return accessToken;
  } catch (error) {
    console.log(error);
  }
}

For more detailed explanation, why your code does not work:

  • You are returning from within a .then() which is not possible
  • If you would want to use the old way of writing async functions, you would need to use:
    • return new Promise((resolve, reject) => { /* Code ... */ }); to wrap your function content
    • resolve(accessToken) instead of return
    • .then() and .catch() instead of await and try/catch
    • and some rejects where you can't resolve anything (so probably in the catch block)

But I would suggest you to use the async/await approach, as it is easier to read.

MauriceNino
  • 6,214
  • 1
  • 23
  • 60
  • 3
    *"You should not mix async/await with the older version .then()."* There are rare exceptions to that rule, but they're rare. :-) Good answer! For what it's worth, a bit of destructuring can be done: `const {user} = await firebase...` – T.J. Crowder Aug 19 '19 at 11:06
  • Thanks for the great explanation @MauriceNino - I had taken those two bit of code from different places and didn't know. – Mr. Robot Aug 19 '19 at 11:10
  • @T.J.Crowder In the same statement? That would be new to me, but I would be more than happy to learn something new! You are definitely right with the destructing, but I would like to not change much about the original code, so that the author can understand better what's changed and what's important about the change. – MauriceNino Aug 19 '19 at 11:10
  • @MauriceNino - Yup, in the same statement, no reason you can't do that. Agreed on not changing too much. Yeah, if I'd been writing the above I probably would have left it as well, then added a postscript or something pointing it out. :-) – T.J. Crowder Aug 19 '19 at 11:32