API de Page Lifecycle

Navegadores compatibles

  • 68
  • 79
  • x
  • x

En la actualidad, los navegadores actualizados a veces suspenden las páginas o las descartan por completo cuando se restringen los recursos del sistema. En el futuro, los navegadores quieren hacer esto de manera proactiva, por lo que consumirán menos energía y memoria. La API de Page Lifecycle proporciona hooks de ciclo de vida para que tus páginas puedan manejar estas intervenciones del navegador de forma segura sin afectar la experiencia del usuario. Observa la API para ver si debes implementar estas funciones en tu aplicación.

Información general

El ciclo de vida de las aplicaciones es una forma clave en la que los sistemas operativos modernos administran los recursos. En Android, iOS y versiones recientes de Windows, el SO puede iniciar y detener apps en cualquier momento. Esto permite que estas plataformas optimicen y reasignen los recursos donde mejor beneficien al usuario.

Históricamente, en la Web no existía ese ciclo de vida, y las apps se pueden mantener activas por tiempo indefinido. Con un gran número de páginas web en ejecución, es posible que los recursos críticos del sistema, como la memoria, la CPU, la batería y la red, se suscriban en exceso, lo que genera una mala experiencia del usuario final.

Si bien desde hace mucho tiempo la plataforma web tiene eventos relacionados con estados del ciclo de vida, como load, unload y visibilitychange, estos eventos solo permiten a los desarrolladores responder a los cambios de estado del ciclo de vida iniciados por el usuario. Para que la Web funcione de manera confiable en dispositivos con baja energía (y sea más consciente de los recursos en general en todas las plataformas), los navegadores necesitan una forma de reclamar y reasignar de forma proactiva los recursos del sistema.

De hecho, en la actualidad, los navegadores ya toman medidas activas para conservar los recursos de las páginas en pestañas en segundo plano, y a muchos navegadores (especialmente Chrome) les gustaría hacer mucho más de esto para disminuir su uso general de recursos.

El problema es que, actualmente, los desarrolladores no tienen forma de prepararse para estos tipos de intervenciones iniciadas por el sistema ni de saber que están sucediendo. Esto significa que los navegadores deben ser conservadores o correr el riesgo de que las páginas web dejen de funcionar.

La API de Page Lifecycle intenta resolver este problema de la siguiente manera:

  • Introducción y estandarización del concepto de estados del ciclo de vida en la Web
  • Definición de estados nuevos iniciados por el sistema que permiten que los navegadores limiten los recursos que pueden consumir las pestañas ocultas o inactivas
  • Crear APIs y eventos nuevos que permitan a los desarrolladores web responder a las transiciones desde y hacia estos nuevos estados iniciados por el sistema

Esta solución proporciona la previsibilidad que necesitan los desarrolladores web para compilar aplicaciones resistentes a las intervenciones del sistema y permite que los navegadores optimicen los recursos del sistema de forma más agresiva, lo que beneficia a todos los usuarios web.

En el resto de esta publicación, se presentarán las nuevas funciones del ciclo de vida de las páginas y se explorará cómo se relacionan con todos los estados y eventos existentes de la plataforma web. También proporcionará recomendaciones para los tipos de trabajo que los desarrolladores deben (y no deben) realizar en cada estado.

Descripción general de los estados y eventos del ciclo de vida de la página

Todos los estados del ciclo de vida de la página son discretos y excluyentes mutuamente, lo que significa que una página solo puede estar en un estado a la vez. Además, la mayoría de los cambios en el estado del ciclo de vida de una página, en general, se pueden observar a través de eventos del DOM (consulta las recomendaciones para desarrolladores para cada estado para conocer las excepciones).

Es posible que la manera más fácil de explicar los estados del ciclo de vida de una página, así como los eventos que señalan las transiciones entre ellos, sea con un diagrama:

Flujo de eventos y estados de la API de Lifecycle de página Representación visual del flujo de estados y eventos descrito en este documento.

Estados

En la siguiente tabla, se explica cada estado en detalle. Además, se enumeran los estados posibles que pueden estar antes y después, así como los eventos que los desarrolladores pueden usar para observar los cambios.

Estado Descripción
Activa

Una página se encuentra en el estado activa si es visible y tiene foco de entrada.

Posibles estados anteriores:
pasivo (a través del evento focus)
congelado (a través del evento resume y, luego, el evento pageshow)

Posibles próximos estados:
pasivo (a través del evento blur)

Pasivo

Una página se encuentra en estado pasivo si es visible y no tiene foco de entrada.

Posibles estados anteriores:
activo (a través del evento blur)
oculto (a través del evento visibilitychange)
congelado (a través del evento resume y, luego, el evento pageshow{/22)

Próximos estados posibles:
activo (a través del evento focus)
oculto (a través del evento visibilitychange)

Oculto

Una página se encuentra en estado oculta si no es visible (y no se congela, se descarta ni se cierra).

Posibles estados anteriores:
pasivo (a través del evento visibilitychange)
congelado (a través del evento resume y, luego, pageshow)

Posibles estados siguientes:
pasivo (a través del evento visibilitychange)
congelado (a través del evento freeze)
descartada (no se activaron eventos)
finalizado (no se activaron eventos)

Con efecto congelado

En el estado inmóvil, el navegador suspende la ejecución de las tareas congelables en las listas de tareas en cola de la página hasta que se desbloquea la página. Eso significa que no se ejecutan los cronómetros de JavaScript y las devoluciones de llamada de recuperación. Las tareas que ya están en ejecución pueden finalizar (lo más importante, la devolución de llamada freeze), pero es posible que tengan limitaciones en cuanto a lo que pueden hacer y el tiempo que pueden ejecutarse.

Los navegadores inmovilizan páginas como una manera de preservar el uso de la CPU, la batería y los datos. También lo hacen para permitir navegaciones hacia atrás y hacia adelante más rápidas, lo que evita la necesidad de volver a cargar por completo la página.

Posibles estados anteriores:
Oculta (mediante el evento freeze)

Posibles estados siguientes:
activo (a través del evento resume; luego, el evento pageshow) pageshow pageshow
pasivo resume y, luego, del pageshowoculto)

oculto{/20

resume

Resuelto

Una página se encuentra en el estado finalizada una vez que se comenzó a descargar y el navegador la borró de la memoria. No se pueden iniciar tareas nuevas en este estado, y las tareas en curso se pueden finalizar si se ejecutan durante demasiado tiempo.

Posibles estados anteriores:
oculto (mediante el evento pagehide)

Posibles próximos estados:
NINGUNO

Descartado

Una página se encuentra en el estado descartada cuando el navegador la descarga para conservar recursos. No se pueden ejecutar tareas, devoluciones de llamadas de eventos ni JavaScript de ningún tipo en este estado, ya que los descartes suelen producirse bajo restricciones de recursos, en las que es imposible iniciar procesos nuevos.

En el estado descartada, la pestaña en sí (incluidos el título y el ícono de página ) suele ser visible para el usuario, aunque la página ya no esté.

Posibles estados anteriores:
oculto (no se activaron eventos)
inhabilitado (no se activaron eventos)

Posibles próximos estados:
NINGUNO

Eventos

Los navegadores envían muchos eventos, pero solo una pequeña parte de ellos indica un posible cambio en el estado del ciclo de vida de la página. En la siguiente tabla, se describen todos los eventos que pertenecen al ciclo de vida y se enumeran a qué estados pueden cambiar.

Nombre Detalles
focus

Se enfoca un elemento del DOM.

Nota: Un evento focus no necesariamente indica un cambio de estado. Solo señala un cambio de estado si la página no tenía foco de entrada en la página.

Posibles estados anteriores:
pasivo

Estados actuales posibles:
activo

blur

Un elemento del DOM perdió el enfoque.

Nota: Un evento blur no necesariamente indica un cambio de estado. Solo señala un cambio de estado si la página ya no tiene foco de entrada (es decir, si la página no cambió el enfoque de un elemento a otro).

Posibles estados anteriores:
activo

Posibles estados actuales:
pasivo

visibilitychange

Cambió el valor de visibilityState del documento. Esto puede ocurrir cuando un usuario navega a una página nueva, cambia de pestaña, la cierra, minimiza o cierra el navegador, o cambia de app en los sistemas operativos para dispositivos móviles.

Posibles estados anteriores:
pasivo
oculto

Posibles estados actuales:
pasivo
oculto

freeze *

La página se acaba de inmovilizar. No se iniciarán las tareas inmovilizables de las listas de tareas en cola de la página.

Posibles estados anteriores:
oculto

Posibles estados actuales:
Inhabilitado

resume *

El navegador reanudó una página congelada.

Posibles estados anteriores:
Inhabilitado

Posibles estados actuales:
activo (si sigue el evento pageshow)
pasivo (si sigue el evento pageshow)
oculto

pageshow

Se está transfiriendo una entrada del historial de sesión.

Puede ser una carga de página nueva o una página extraída de la memoria caché atrás/adelante. Si la página se tomó de la memoria caché atrás/adelante, la propiedad persisted del evento es true; de lo contrario, es false.

Posibles estados anteriores:
congelado (también se habría activado un evento resume)

Posibles estados actuales:
activo
pasivo
oculto

pagehide

Se está transfiriendo una entrada del historial de sesión.

Si el usuario navega a otra página y el navegador puede agregar la página actual a la memoria caché atrás/adelante para volver a utilizarla más adelante, la propiedad persisted del evento será true. Cuando se establece true, la página ingresa al estado congelado; de lo contrario, ingresa al estado finalizado.

Posibles estados anteriores:
oculto

Posibles estados actuales:
Inmóvil (event.persisted es verdadero, freeze evento sigue)
finalizado (event.persisted es falso, unload sigue el evento)

beforeunload

La ventana, el documento y sus recursos están a punto de descargarse. El documento sigue siendo visible y el evento aún se puede cancelar en este momento.

Importante: El evento beforeunload solo debe usarse para alertar al usuario sobre los cambios no guardados. Una vez que se guarden esos cambios, se debe quitar el evento. Nunca debe agregarse incondicionalmente a la página, ya que hacerlo puede afectar el rendimiento en algunos casos. Consulta la sección de APIs heredadas para obtener más detalles.

Posibles estados anteriores:
oculto

Estados actuales posibles:
finalizado

unload

Se está descargando la página.

Advertencia: Nunca se recomienda usar el evento unload, ya que no es confiable y puede afectar el rendimiento en algunos casos. Consulta la sección de APIs heredadas para obtener más detalles.

Posibles estados anteriores:
oculto

Posibles estados actuales:
Finalizado

* Indica un evento nuevo definido por la API de Page Lifecycle.

Nuevas funciones agregadas en Chrome 68

En el gráfico anterior, se muestran dos estados que se iniciaron por el sistema en lugar de por el usuario: congelado y descartado. Como se mencionó anteriormente, en la actualidad, los navegadores inmovilizan y descartan las pestañas ocultas de vez en cuando (a su discreción), pero los desarrolladores no tienen forma de saber cuándo sucede esto.

En Chrome 68, los desarrolladores ahora pueden observar los eventos freeze y resume en document para observar cuándo una pestaña oculta se inmoviliza y desbloquea.

document.addEventListener('freeze', (event) => {
  // The page is now frozen.
});

document.addEventListener('resume', (event) => {
  // The page has been unfrozen.
});

En Chrome 68, el objeto document ahora también incluye una propiedad wasDiscarded. Para determinar si una página se descartó mientras estaba en una pestaña oculta, puedes inspeccionar el valor de esta propiedad en el tiempo de carga de la página. Ten en cuenta que las páginas descartadas se deben volver a cargar para usarlas de nuevo.

if (document.wasDiscarded) {
  // Page was previously discarded by the browser while in a hidden tab.
}

Para obtener consejos sobre lo que es importante hacer en los eventos freeze y resume, y sobre cómo controlar y prepararse para el descarte de páginas, consulta las recomendaciones para desarrolladores para cada estado.

En las siguientes secciones, se ofrece una descripción general de la forma en que estas funciones nuevas se ajustan a los estados y eventos existentes de la plataforma web.

Cómo observar los estados del ciclo de vida de la página en el código

En los estados activo, pasivo y oculto, es posible ejecutar código JavaScript que determine el estado actual del ciclo de vida de la página a partir de las APIs de plataformas web existentes.

const getState = () => {
  if (document.visibilityState === 'hidden') {
    return 'hidden';
  }
  if (document.hasFocus()) {
    return 'active';
  }
  return 'passive';
};

Por otro lado, los estados congelado y finalizado solo se pueden detectar en su respectivo objeto de escucha de eventos (freeze y pagehide) a medida que cambia el estado.

Observa los cambios de estado

A partir de la función getState() definida anteriormente, puedes observar todos los cambios de estado del ciclo de vida de la página con el siguiente código.

// Stores the initial state using the `getState()` function (defined above).
let state = getState();

// Accepts a next state and, if there's been a state change, logs the
// change to the console. It also updates the `state` value defined above.
const logStateChange = (nextState) => {
  const prevState = state;
  if (nextState !== prevState) {
    console.log(`State change: ${prevState} >>> ${nextState}`);
    state = nextState;
  }
};

// Options used for all event listeners.
const opts = {capture: true};

// These lifecycle events can all use the same listener to observe state
// changes (they call the `getState()` function to determine the next state).
['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach((type) => {
  window.addEventListener(type, () => logStateChange(getState(), opts));
});

// The next two listeners, on the other hand, can determine the next
// state from the event itself.
window.addEventListener('freeze', () => {
  // In the freeze event, the next state is always frozen.
  logStateChange('frozen');
}, opts);

window.addEventListener('pagehide', (event) => {
  // If the event's persisted property is `true` the page is about
  // to enter the back/forward cache, which is also in the frozen state.
  // If the event's persisted property is not `true` the page is
  // about to be unloaded.
  logStateChange(event.persisted ? 'frozen' : 'terminated');
}, opts);

El código anterior hace tres cosas:

  • Establece el estado inicial con la función getState().
  • Define una función que acepta un estado siguiente y, si hay un cambio, registra los cambios de estado en la consola.
  • Agrega objetos de escucha de eventos de captura para todos los eventos de ciclo de vida necesarios, que, a su vez, llaman a logStateChange() y pasan el siguiente estado.

Un aspecto que debes tener en cuenta sobre el código anterior es que todos los objetos de escucha de eventos se agregan a window y todos pasan {capture: true}. Esto se debe a varios motivos:

  • No todos los eventos del ciclo de vida de la página tienen el mismo destino. pagehide y pageshow se activan en window; visibilitychange, freeze y resume se activan en document, y focus y blur se activan en sus respectivos elementos del DOM.
  • La mayoría de estos eventos no aparecen como burbujas, lo que significa que es imposible agregar objetos de escucha de eventos que no capturan a un elemento principal común y observarlos todos.
  • La fase de captura se ejecuta antes que las fases de destino o de burbuja, por lo que agregar objetos de escucha te ayuda a garantizar que se ejecuten antes de que otro código pueda cancelarlos.

Recomendaciones para desarrolladores para cada estado

Como desarrollador, es importante comprender los estados del ciclo de vida de la página y cómo observarlos en el código, ya que el tipo de trabajo que debes (y no) depende en gran medida del estado en el que se encuentra tu página.

Por ejemplo, claramente no tiene sentido mostrar una notificación transitoria al usuario si la página se encuentra en estado oculto. Si bien este ejemplo es bastante obvio, hay otras recomendaciones que no son tan obvias que vale la pena mencionar.

Estado Recomendaciones para desarrolladores
Active

El estado activo es el momento más crítico para el usuario y, por lo tanto, el tiempo más importante para que tu página pueda responder a las entradas del usuario.

Cualquier trabajo que no sea de IU y que pueda bloquear el subproceso principal no se debe asignar a períodos de inactividad o se descarga a un trabajador web.

Passive

En el estado pasivo, el usuario no está interactuando con la página, pero aún puede verla. Esto significa que las actualizaciones y animaciones de la IU deberían seguir siendo fluidas, pero el momento en que se producen es menos crítico.

Cuando la página cambia de activa a pasiva, es un buen momento para conservar el estado de la aplicación no guardado.

Hidden

Cuando la página cambia de pasiva a oculta, es posible que el usuario no vuelva a interactuar con ella hasta que se vuelva a cargar.

La transición a oculto también suele ser el último cambio de estado que los desarrolladores pueden observar de manera confiable (en especial, en dispositivos móviles, ya que los usuarios pueden cerrar pestañas o la app de navegador en sí, y los eventos beforeunload, pagehide y unload no se activan en esos casos).

Esto significa que debes tratar el estado oculto como el final probable de la sesión del usuario. En otras palabras, conservar cualquier estado de aplicación no guardado y enviar datos de estadísticas no enviados.

También debes dejar de realizar actualizaciones de la IU (ya que el usuario no las verá) y debes detener las tareas que un usuario no quiere que se ejecuten en segundo plano.

Frozen

En el estado inmovilizado, las tareas inmovilizadas de las listas de tareas en cola se suspenden hasta que se desbloquea la página, lo que puede no suceder nunca (p.ej., si se descarta la página).

Por lo tanto, cuando la página cambia de oculta a inmovilizada, es fundamental que detengas los cronómetros o elimines las conexiones que, si se inmovilizan, podrían afectar a otras pestañas abiertas en el mismo origen o afectar la capacidad del navegador para colocar la página en la memoria caché atrás/adelante.

En particular, es importante que hagas lo siguiente:

También debes conservar cualquier estado de vista dinámica (p.ej., la posición de desplazamiento en una vista de lista infinita) en sessionStorage (o IndexedDB a través de commit()) que deseas restablecer si la página se descartara y se recargara más tarde.

Si la página pasa de congelada a oculta, puedes volver a abrir las conexiones cerradas o reiniciar los sondeos que hayas detenido cuando la página se bloqueó inicialmente.

Terminated

Por lo general, no es necesario que realices ninguna acción cuando una página pase al estado terminated.

Dado que las páginas que se descargan como resultado de una acción del usuario siempre pasan por el estado oculto antes de pasar al estado finalizado, en el estado oculto se debe realizar la lógica de finalización de la sesión (p.ej., el estado de la aplicación persistente y la generación de informes para las estadísticas).

Además (como se mencionó en las recomendaciones para el estado oculto), es muy importante que los desarrolladores sepan que la transición al estado finalizado no se puede detectar de manera confiable en muchos casos (especialmente en dispositivos móviles), por lo que es probable que los desarrolladores que dependen de los eventos de finalización (p.ej., beforeunload, pagehide y unload) estén perdiendo datos.

Discarded

Los desarrolladores no pueden observar el estado descartada en el momento en que se descarta una página. Esto se debe a que las páginas se suelen descartar bajo restricciones de recursos y, en la mayoría de los casos, no es posible inmovilizar una página solo para permitir que se ejecute la secuencia de comandos en respuesta a un evento de descarte.

Como resultado, debes prepararte para el descarte del cambio de hidden a congelado y, luego, puedes reaccionar a la restauración de una página descartada en el tiempo de carga de la página. Para ello, consulta document.wasDiscarded.

Una vez más, debido a que la confiabilidad y el orden de los eventos de ciclo de vida no se implementan de manera coherente en todos los navegadores, la forma más fácil de seguir las sugerencias de la tabla anterior es usar PageLifecycle.js.

APIs de ciclo de vida heredadas que se deben evitar

El evento de descarga

Muchos desarrolladores tratan el evento unload como una devolución de llamada garantizada y lo usan como un indicador de fin de sesión para guardar el estado y enviar datos de estadísticas. Sin embargo, esto es sumamente poco confiable, sobre todo en dispositivos móviles. El evento unload no se activa en muchas situaciones de descarga típicas, como cerrar una pestaña desde el selector de pestañas en un dispositivo móvil o cerrar la app del navegador desde el selector de apps.

Por este motivo, siempre es mejor confiar en el evento visibilitychange para determinar cuándo finaliza una sesión y considerar el estado oculto como el último momento confiable para guardar los datos de la app y del usuario.

Además, la mera presencia de un controlador de eventos unload registrado (a través de onunload o addEventListener()) puede impedir que los navegadores coloquen páginas en la memoria caché atrás/adelante para lograr cargas de retroceso y adelantamiento más rápido.

En todos los navegadores modernos, se recomienda usar siempre el evento pagehide para detectar posibles descargas de páginas (es decir, el estado finalizado) en lugar del evento unload. Si necesitas compatibilidad con Internet Explorer 10 y versiones anteriores, debes detectar el evento pagehide y solo usar unload si el navegador no es compatible con pagehide:

const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';

window.addEventListener(terminationEvent, (event) => {
  // Note: if the browser is able to cache the page, `event.persisted`
  // is `true`, and the state is frozen rather than terminated.
});

El evento beforeunload

El evento beforeunload tiene un problema similar al evento unload porque, desde el punto de vista histórico, la presencia de un evento beforeunload podría impedir que las páginas sean aptas para el almacenamiento en la memoria caché atrás/adelante. Los navegadores modernos no tienen esta restricción. Sin embargo, algunos navegadores, como precaución, no activarán el evento beforeunload cuando intenten incluir una página en la memoria caché atrás/adelante, lo que significa que el evento no es confiable como indicador de fin de sesión. Además, algunos navegadores (incluido Chrome) requieren una interacción del usuario en la página antes de permitir que se active el evento beforeunload, lo que afecta aún más su confiabilidad.

Una diferencia entre beforeunload y unload es que hay usos legítimos de beforeunload. Por ejemplo, si deseas advertir al usuario que tiene cambios sin guardar, los perderás si continúa descargando la página.

Dado que existen motivos válidos para usar beforeunload, te recomendamos que solo agregues objetos de escucha beforeunload cuando un usuario tenga cambios sin guardar y, luego, los quites inmediatamente después de guardarlos.

En otras palabras, no hagas esto (ya que agrega un objeto de escucha beforeunload de forma incondicional):

addEventListener('beforeunload', (event) => {
  // A function that returns `true` if the page has unsaved changes.
  if (pageHasUnsavedChanges()) {
    event.preventDefault();

    // Legacy support for older browsers.
    return (event.returnValue = true);
  }
});

En cambio, haz lo siguiente (dado que solo agrega el objeto de escucha beforeunload cuando sea necesario y lo quita cuando no lo sea):

const beforeUnloadListener = (event) => {
  event.preventDefault();
  
  // Legacy support for older browsers.
  return (event.returnValue = true);
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  addEventListener('beforeunload', beforeUnloadListener);
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  removeEventListener('beforeunload', beforeUnloadListener);
});

Preguntas frecuentes

¿Por qué no aparece el estado "cargando"?

La API de Page Lifecycle define los estados como discretos y mutuamente excluyentes. Dado que una página se puede cargar en estado activo, pasivo u oculto, y como puede cambiar de estado (o incluso cerrarse) antes de que termine de cargarse, un estado de carga separado no tiene sentido dentro de este paradigma.

Mi página hace un trabajo importante cuando está oculta, ¿cómo puedo evitar que se inmovilice o descarte?

Existen muchas razones legítimas por las que las páginas web no se deberían congelar mientras se ejecutan en estado oculto. El ejemplo más obvio es una app que reproduce música.

También hay situaciones en las que sería riesgoso que Chrome descarte una página, por ejemplo, si contiene un formulario con una entrada del usuario que no se envió o si tiene un controlador beforeunload que advierte cuando se descarga la página.

Por el momento, Chrome será conservador cuando descarte páginas y solo lo hará cuando esté seguro de que no afectará a los usuarios. Por ejemplo, no se descartarán las páginas en las que se haya observado alguna de las siguientes acciones en el estado oculto, a menos que se encuentren bajo restricciones de recursos extremas:

  • Reproduciendo audio
  • Cómo usar WebRTC
  • Actualiza el título o el ícono de página de la tabla
  • Mostrando alertas
  • Envío de notificaciones push

A fin de conocer las funciones actuales de la lista que se usan para determinar si una pestaña se puede congelar o descartar de forma segura, consulta Heurística para congelar y descartar en Chrome.

¿Qué es la memoria caché atrás/adelante?

La memoria caché atrás/adelante es un término que se usa para describir una optimización de navegación que implementan algunos navegadores y que agiliza el uso de los botones atrás y adelante.

Cuando un usuario sale de una página, estos navegadores inmovilizan una versión de esa página para que pueda reanudarla rápidamente en caso de que el usuario navegue hacia atrás con los botones para retroceder o avanzar. Recuerda que agregar un controlador de eventos unload evita que esta optimización sea posible.

Para todos los intents y propósitos, esta congelación es funcionalmente la misma que hacen los navegadores congelados para conservar la CPU y la batería; por esa razón, se considera parte del estado de ciclo de vida congelado.

¿Cómo puedo guardar datos en IndexedDB si no puedo ejecutar APIs asíncronas en los estados inmovilizado o finalizado?

En los estados inmovilizados y finalizados, las tareas que se pueden inmovilizar en las listas de tareas en cola de una página se suspenden, lo que significa que las APIs asíncronas y basadas en devoluciones de llamada, como IndexedDB, no se pueden usar de manera confiable.

En el futuro, agregaremos un método commit() a los objetos IDBTransaction, lo que les permitirá a los desarrolladores realizar transacciones de solo escritura que no requieren devoluciones de llamada. En otras palabras, si el desarrollador solo escribe datos en IndexedDB y no realiza una transacción compleja que consista en lecturas y escrituras, el método commit() podrá finalizar antes de que se suspendan las listas de tareas en cola (suponiendo que la base de datos de IndexedDB ya está abierta).

Sin embargo, para el código que necesita funcionar en la actualidad, los desarrolladores tienen dos opciones:

  • Usa el almacenamiento de sesiones: El almacenamiento de sesiones es síncrono y se conserva entre los descartes de páginas.
  • Usar IndexedDB desde el service worker: Un service worker puede almacenar datos en IndexedDB después de que se cierre la página o se descarte. En el objeto de escucha de eventos freeze o pagehide, puedes enviar datos al service worker a través de postMessage(), y este podrá controlar el guardado de los datos.

Prueba tu app en los estados congelado y descartado

Para probar cómo se comporta tu app en los estados inmovilizado y descartado, puedes visitar chrome://discards para bloquear o descartar cualquiera de las pestañas abiertas.

Chrome descarta la IU

Esto te permite asegurarte de que tu página maneje correctamente los eventos freeze y resume, así como la marca document.wasDiscarded cuando se vuelven a cargar las páginas después de un descarte.

Resumen

Los desarrolladores que deseen respetar los recursos del sistema de los dispositivos de sus usuarios deben compilar sus apps teniendo en cuenta los estados del ciclo de vida de la página. Es fundamental que las páginas web no consuman recursos del sistema excesivos en situaciones que el usuario no esperaría

Cuantos más desarrolladores comiencen a implementar las nuevas APIs de Page Lifecycle, más seguro será que los navegadores se bloqueen y descarte las páginas que no se estén usando. Esto significa que los navegadores consumirán menos memoria, CPU, batería y recursos de red, lo que es una ventaja para los usuarios.