El evento 'beforeunload' se dispara cuando la página se deja en segundo plano en Android

8

Estoy tratando de hacer una rueda de carga simple que aparece al navegar. Aparece usando un evento 'beforeunload' cuando se aleja y usa el evento 'load' para ocultarse nuevamente cuando termina.

El problema es que cuando dejo la página en segundo plano en mi teléfono, por ejemplo, durante unas horas, el evento 'beforeunload' se dispara y muestra la rueda giratoria. Probablemente porque Chrome en Android está descargando parcialmente la página para ahorrar memoria. Sin embargo, la ruleta no desaparece por sí sola y parece que no puedo entender cómo hacer que desaparezca nuevamente de una manera elegante.

¿Hay algún otro evento que debería usar en su lugar?

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

    window.addEventListener("beforeunload", function() {
        topSpinner.classList.remove("closed");
    });
Doskii
fuente
mismo problema aquí :-(
rabudde
2
He creado un violín para esto: jsfiddle.net/ov6b9pdL Abra esto en su navegador móvil Chrome (Android?). Apague la pantalla durante 5-10 minutos y vuelva al navegador. En mi caso puedo ver la capa de carga.
rabudde

Respuestas:

3

Chrome 68 (julio de 2018) introdujo una nueva API de ciclo de vida de la página : el diagrama de estado suministrado en este enlace no muestra la llamada del sistema (navegador)beforeunload antes de poner la página en el frozenestado, pero eso es claramente lo que está sucediendo.

Con mucha ayuda, la API introdujo dos nuevos eventos que se activan cuando la página entra y sale de este estado: freezeyresume .

He resuelto este problema en las pantallas de Chrome Mobile y Webview simplemente agregando esto:

document.addEventListener('resume', (event) => {
  // The page has been unfrozen: remove the spinner if it's active
 topSpinner.classList.add("closed");
});
mhepton
fuente
Veo la solución, pero ¿alguna idea sobre la posible causa? Además, parece que desde la API Lifecycle de la página es posible que después de 'beforeUnload' se congele y luego se reviva. Pero supongo que esto sería difícil de rastrear / depurar.
Winston Jude
0

Cambiar la lista de eventos de carga para enfocar

David Bradshaw
fuente
0

He registrado eventos a través de Ajax a la base de datos. Mis pruebas mostraron que no es predecible qué eventos se activaron (es decir, cuando se usa PWA). Hay focus, visibilitychange, resizey beforeunloadparticipan. Me sorprendió cuando encendí la pantalla con PWA activa, a veces beforeunloadson los únicos eventos que se han registrado en la base de datos.

Estoy usando el siguiente código ahora, que parece funcionar sin efectos secundarios:

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);
    }
});
rabudde
fuente
0

Intente mantener una marca de cargador a través de localStorage, así que si la página se vuelve a cargar, verifique la bandera nuevamente:

Pseudo código a continuación:

$(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);
  }
};
Ahed Kabalan
fuente
Esto no ayudaría para el caso de uso de OP, porque cuando se enciende la pantalla del móvil desde el modo de espera, la página no se recarga realmente.
rabudde
Entonces, ¿tal vez usando la función setTimeout cada x segundos para verificar el estado podría ser útil en tal caso?
Ahed Kabalan
No es muy fácil de usar. Imagine una situación en la que enciende la pantalla de su dispositivo móvil con el navegador abierto. Lo primero que verá es el ícono del cargador que se eliminará setTimeoutdespués de unos xsegundos, por lo que, en el peor de los casos, tendrá que esperar xsegundos para volver a ver la página. Además, usar un temporizador que esté funcionando todo el tiempo para este caso especial no es realmente innovador.
rabudde
No, me refiero al temporizador para verificar el valor de la bandera anterior.
Ahed Kabalan
No se a que te refieres. Edite su código para mostrar cómo debería funcionar esto.
rabudde