Doskii
Doskii

Reputation: 146

'beforeunload' event triggers when page is left in the background on Android

I'm trying to make a simple loading spinner that pops up when navigating. It shows up using a 'beforeunload' event when navigating away and uses the 'load' event to hide itself again when it is done.

The problem is that when I leave the page in the background on my phone for e.g. a few hours the 'beforeunload' event triggers and displays the spinner. Probably because Chrome on Android is partially unloading the page to save memory. The spinner doesn't go away by itself though and I can't seem to figure out how to make it disappear again in an elegant way.

Is there any other event I should be using instead?

    window.addEventListener("load", function() {
        topSpinner.classList.add("closed");
    });

    window.addEventListener("beforeunload", function() {
        topSpinner.classList.remove("closed");
    });

Upvotes: 10

Views: 3145

Answers (4)

rabudde
rabudde

Reputation: 7722

I've logged events via Ajax to database. My tests showed, that it's not predictable which events were triggered (i.e. when using PWA). There are focus, visibilitychange, resize and beforeunload involved. I was surprised about when switching screen on with active PWA, sometimes beforeunload is the only events that has been logged to database.

I'm using the following code now, that I've found at Kleiderliebe, which seems to work without sideeffects:

var visibilityState = 'visible';
window.addEventListener('beforeunload', function(e) {
    if (visibilityState === 'visible') {
        loader.show(e);
    }
});
window.addEventListener('focus', loader.hide);
window.addEventListener('resize', loader.hide);
window.addEventListener('visibilitychange', function(e) {
    visibilityState = document.visibilityState;
    if (visibilityState === 'visible') {
        loader.hide(e);
    }
});

Upvotes: 0

mhepton
mhepton

Reputation: 128

Chrome 68 (July 2018) introduced a new Page Lifecycle API: the state diagram supplied in this link does not show the System (browser) calling beforeunload before putting the page into the frozen state, but that is clearly what is happening.

Helpfully, the API introduced two new events that trigger as the page enters and exits this state: freeze and resume.

I've solved this problem on both mobile chrome and webview displays simply by adding this:

document.addEventListener('resume', (event) => {
  // The page has been unfrozen: remove the spinner if it's active
 topSpinner.classList.add("closed");
});

Upvotes: 6

Ahed Kabalan
Ahed Kabalan

Reputation: 855

Try to persist a loader flag via localStorage, so if the page then reloaded, check the flag again:

Pseudo code below:

$(document).ready(function() {

  $('#loader').hide();
  localStorage.setItem("loader", false);

  window.addEventListener('beforeunload', showLoader);
});

var showLoader = function() {
  var isShow = localStorage.getItem("loader");
  if(!isShow){
      $('#loader').show();
      localStorage.setItem("loader", true);
  }
};

Upvotes: 0

David Bradshaw
David Bradshaw

Reputation: 13077

Change the load event listerner to focus

Upvotes: 0

Related Questions