September 4, 2018 ~ 4 min read

Ionic 3: Better Dialogs with async/await


Originally posted on Medium.

When building a mobile app with Ionic there is a good chance you will want to display confirm dialogs to your users to ask them if they really want to do something, for example before logging them out of your application.

Fortunately Ionic comes with an AlertController that can handle dialogs like alerts, confirms and prompts. Unfortunately, though, the example usage explained in the Ionic docs is kind of clumsy and hard to read. That’s why I decided to develop a better approach. In this post I am going to explain why and how I did that. (tl;dr, just take me to the solution!)

So let’s look at an example based on the Ionic docs where you ask for confirmation before logging out the user:

public logout() {
  const confirm = this.alertController.create({
    title: 'Are you sure?',
    message: 'Do you really want to log out?',
    buttons: [
      {
        text: 'Cancel',
        role: 'cancel',
        handler: () => {
          // do nothing, user tapped cancel
        }
      },
      {
        text: 'OK',
        handler: () => {
          this.authService.logout().then(() => {
            // do something after logout, for example redirect to login page
            // this method maybe
            // has a lot of lines
            // of code as well
            // right?
          });
        }
      }
    ]
  });

  confirm.present();
}

So this works fine of course, but I think it is not the most beautiful solution.

Why, you ask?

You would have to read through lots of lines of code to see what is actually happening when the user confirms the logout. I usually like to split up huge methods into smaller ones, also keeping the separation of concerns principle in mind.

So what I usually did was splitting up the code into two methods, one responsible for displaying the dialog and one responsible for the actual logout process:

public logout() {
  const confirm = this.alertController.create({
    title: 'Are you sure?',
    message: 'Do you really want to log out?',
    buttons: [
      {
        text: 'Cancel',
        role: 'cancel',
        handler: () => {
          // do nothing, user tapped cancel
        }
      },
      {
        text: 'OK',
        handler: () => {
          this.onLogoutConfirmed();
        }
      }
    ]
  });

  confirm.present();
}

private onLogoutConfirmed() {
  this.authService.logout().then(() => {
    // do some magic after logout
  });
}

That seems better, but the there are still a lot of lines to read until you reach the actual logout method. I also did not like this solution very much because of semantics. The method called logout() does not do the actual logging out and I think a button labeled “Logout” should call a method with a similar name and not something like showLogoutConfirmation().

So now what?

async/await

As the post title might reveal my preferred solution is async/await. I had this idea while browsing through the documentation of the upcoming Ionic 4 release where the AlertController will be promisified by default. So why not use this strategy in Ionic 3?

That’s what I came up with and what I really like using right now for dialogs:

public async logout() {
  const confirmation = await this.confirmLogout();

  if (confirmation) {
    this.authService.logout(() => {
      // some other magic happening here
    });
  }
}

private confirmLogout() {
  return new Promise((resolve) => {
    const confirm = this.alertController.create({
      title: 'Are you sure?',
      message: 'Do you really want to logout?',
      buttons: [
        {
          text: 'Cancel',
          role: 'cancel',
          handler: () => {
            return resolve(false);
          },
        },
        {
          text: 'OK',
          handler: () => {
            return resolve(true);
          },
        },
      ],
    });

    confirm.present();
  });
}

We have a method called logout() and one called confirmLogout(). The code is easy to read and each method does exactly what you would expect from their names.