DismissAll Might Not Close All Loading Indicators

January 26th 2018 Ionic 2/3

There are two functions for dismissing a loading indicator instance in Ionic: dismiss and dismissAll. The former will only close the specific instance, while the latter will close all currently opened instances. However, it's better to avoid dismissAll unless you really need it, because it could leave an instance open which would be closed correctly if dismiss was used instead.

Let's look at a simplified example for using the loading indicator:

ionViewDidEnter() {
    let loading = this.loadingCtrl.create();
    loading.present();
    // initialize page
    loading.dismiss();
}

No matter what happens between the present and dismiss calls, even if it's nothing at all as in the code above, the call to dismiss will ensure that the loading indicator is hidden in the end. If I replace dismiss with dismissAll, this is not necessarily the case any more:

ionViewDidEnter() {
    let loading = this.loadingCtrl.create();
    loading.present();
    // initialize page
    loading.dismissAll();
}

If you try this code, the loading indicator will stay on the screen. Why? Because dismissAll is called before the indicator is shown. Let's add some logging to confirm that:

ionViewDidEnter() {
    console.log('entered');
    let loading = this.loadingCtrl.create();
    loading.present().then(() => {
        console.log('presented');
    });
    loading.dismissAll();
    console.log('dismissed');
}

The browser console output will be as follows:

entered
dismissed
presented

If you use dismiss instead of dismissAll, the dismissed instance will still hide immediately after it is displayed, although dismiss was called before present completed, hence avoiding the issue. When using dismissAll, this is not the case. We need to handle this case ourselves:

ionViewDidEnter() {
    let loading = this.loadingCtrl.create();
    let alreadyDismissed = false;
    loading.present().then(() => {
        if (alreadyDismissed) {
            loading.dismissAll();
        }
    });
    loading.dismissAll();
    alreadyDismissed = true;
}

With this change, we repeat the call to dismissAll in the case it was already called before present completed. This will ensure that the loading indicator will get hidden one way or the other.

The above example should be a reason enough not to call dismissAll instead of dismiss unless you have a very good reason for it, i.e. you can't reliably access the loading indicator instance which is currently shown. And even then, you should meticulously think through all the cases to make sure the indicator will be hidden when you expect it to.

Copyright
Creative Commons License