Se mejoró el descarte de páginas en XMLHttpRequest() síncrono

Cómo reducir las navegaciones demoradas

Joe Medley
Joe Medley

Es común que una página o aplicación tenga estadísticas o datos sin enviar cuando un usuario la cierra. Para evitar la pérdida de datos, algunos sitios usan una llamada síncrona a XMLHttpRequest() para mantener la página o la app abierta hasta que se pasen los datos al servidor. No solo hay mejores formas de guardar datos, sino que esta técnica crea una mala experiencia del usuario, ya que retrasa el cierre de la página hasta por varios segundos.

Esta práctica debe cambiar, y los navegadores están respondiendo. La especificación de XMLHttpRequest() ya está programada para su baja y eliminación. Chrome 80 da el primer paso y no permite llamadas síncronas dentro de varios controladores de eventos, específicamente beforeunload, unload, pagehide y visibilitychange cuando se activan en el rechazo. Recientemente, WebKit también implementó una confirmación que implementa el mismo cambio de comportamiento.

En este artículo, describiré brevemente las opciones para quienes necesiten tiempo para actualizar sus sitios y describiré las alternativas a XMLHttpRequest().

Inhabilitaciones temporales

Chrome no quiere dejar de usar XMLHttpRequest(), por lo que hay algunas opciones temporales para inhabilitar esta función. Para los sitios de Internet, hay disponible una prueba de origen. Con esto, agregas un token específico del origen a los encabezados de tu página que habilita las llamadas XMLHttpRequest() síncronas. Esta opción finalizará poco antes del lanzamiento de Chrome 89, en algún momento de marzo de 2021. Los clientes de Chrome Enterprise también pueden usar la marca de política AllowSyncXHRInPageDismissal, que finaliza al mismo tiempo.

Alternativas

Independientemente de cómo envíes los datos al servidor, es mejor evitar esperar hasta que se descargue la página para enviar todos los datos a la vez. Además de crear una mala experiencia del usuario, la descarga no es confiable en los navegadores modernos y corre el riesgo de perder datos si algo sale mal. Específicamente, los eventos de descarga a menudo no se activan en los navegadores para dispositivos móviles, ya que hay muchas formas de cerrar una pestaña o un navegador en sistemas operativos para dispositivos móviles sin que se active el evento unload. Con XMLHttpRequest(), usar cargas útiles pequeñas era una opción. Ahora es un requisito. Ambas alternativas tienen un límite de carga de 64 KB por contexto, como lo requiere la especificación.

Cómo recuperar el estado de keepalive

La API de Fetch proporciona un método sólido para controlar las interacciones del servidor y una interfaz coherente para usar en diferentes APIs de plataformas. Entre sus opciones, se encuentra keepalive, que garantiza que una solicitud continúe, independientemente de si la página que la realizó permanece abierta o no:

window.addEventListener('unload', {
  fetch
('/siteAnalytics', {
    method
: 'POST',
    body
: getStatistics(),
    keepalive
: true
 
});
}

El método fetch() tiene la ventaja de tener un mayor control sobre lo que se envía al servidor. Lo que no muestro en el ejemplo es que fetch() también muestra una promesa que se resuelve con un objeto Response. Como estoy tratando de evitar la descarga de la página, decidí no hacer nada con ella.

SendBeacon()

En realidad, SendBeacon() usa la API de Fetch, por lo que tiene la misma limitación de carga útil de 64 KB y también garantiza que una solicitud continúe después de que se descargue una página. Su principal ventaja es la simplicidad. Te permite enviar tus datos con una sola línea de código:

window.addEventListener('unload', {
  navigator
.sendBeacon('/siteAnalytics', getStatistics());
}

Conclusión

Con la mayor disponibilidad de fetch() en todos los navegadores, es posible que XMLHttpRequest() se quite de la plataforma web en algún momento. Los proveedores de navegadores coinciden en que se debe quitar, pero esto llevará tiempo. Dar de baja uno de sus peores casos de uso es un primer paso que mejora la experiencia del usuario para todos.

Foto de Matthew Hamilton en Unsplash