Rewriting promises with async/await, seeking for clarification

Viewed 1507

I have two functions that handle Facebook login/logout on my front-end and both of them are written with promises. I want to rewrite these using async/await.

The original code with promises:

export function login() {
  return new Promise<facebookSdk.IAuthResponse>((resolve, reject) => {
    FB.login((response) => {
      if (response.authResponse) {
        resolve(response)
      } else {
        reject(errors.facebookLoginError)
      }
    })
  })
}

export function logout() {
  return new Promise<facebookSdk.IAuthResponse>((resolve) => {
    FB.logout((response) => {
      resolve(response)
    })
  })
}

Here's how I wrote them using async/await:

function promiseFacebookLogin(): Promise<facebookSdk.IAuthResponse | Error> {
  return new Promise<facebookSdk.IAuthResponse>((resolve, reject) => {
    FB.login((response) => {
      if (response.authResponse) {
        resolve(response)
      } else {
        reject(errors.facebookLoginError)
      }
    })
  })
}

export async function login(): Promise<facebookSdk.IAuthResponse | Error> {
  try {
    return await promiseFacebookLogin()
  } catch (err) {
    throw err
  }
}

export async function logout(): Promise<facebookSdk.IAuthResponse | void> {
  try {
    return await FB.logout((response) => {
      return response
    })
  } catch (err) {
    throw err
  }
}

The resulting code works as intended but there's something I want to clarify. As you can see, I can get rid of the entire promise syntax for logout function. However when it comes to the login function, I was unable to do so. I had to wrap the promise separately and await the result of that. As far as I researched, this seems to be common practice for callback taking functions.

Can somebody shed some light on why is it not possible to get rid of the Promise syntax completely on the login function?

3 Answers

I'm afraid that you can't rewrite the export functions because of the limitations from the usage of FB.login and FB.logout functions. The reason is that they don't return a promise. But if for example FB adapted, and changed the functions behavior to return a promise that resolves to the response (or throw an error if response.authResponse is false), then you can use the one suggested by @Saravana in his fiddle.

So for the moment, trying to rewrite your current login and logout functions will just introduce more code. What you can do is to keep them like that (because they are okay like that) and when you call the functions somewhere, you can await them because you know that they already return a promise. e.g.

// at some distant part of your code base
async function someFunc() {
  try:
    // await the response which is the one resolved in the callback function
    // inside the FB.login call
    let fbLoginResponse = await login();

    // ... do something with the response here ...

  catch (err) {
    // the error here is errors.facebookLoginError because
    // it's the one rejected in the callback function in the FB.login call
    console.log('You are not authenticated! Please try again.');
  }
}

Related