Es común que una página o una app tenga datos de estadísticas o de otro tipo que no se hayan enviado cuando un usuario la cierra. Para evitar la pérdida de datos, algunos sitios usan una llamada síncrona a XMLHttpRequest() para mantener abierta la página o la app hasta que sus datos se pasen 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. Ya se programó la baja y la eliminación de la XMLHttpRequest()
especificaciónpara su baja y. Chrome 80 da el primer
paso al no permitir llamadas síncronas dentro de varios controladores de eventos,
específicamente beforeunload, unload, pagehide y visibilitychange cuando
se activan en el descarte. WebKit también publicó recientemente una confirmación que implementa
el mismo cambio de comportamiento.
Describiré brevemente las opciones para quienes necesiten tiempo para actualizar sus sitios y describiré las alternativas a XMLHttpRequest().
Inhabilitaciones temporales
Chrome quiere ofrecer tiempo de desarrollo para quitar la dependencia de XMLHttpRequest(), por lo que ofrecemos opciones de inhabilitación temporales.
Únete a una prueba de origen. Con esto, agregas un token específico del origen a los encabezados de tu página que habilita las llamadas síncronas XMLHttpRequest(). Esta opción finaliza 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 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. En particular, los eventos de descarga a menudo no se activan en los navegadores
para dispositivos móviles
porque 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, según lo requiere la especificación.
Fetch keepalive
La API de Fetch
proporciona un medio sólido para abordar 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, ya sea que la página que la realizó permanezca abierta o no:
window.addEventListener('unload', {
fetch('/siteAnalytics', {
method: 'POST',
body: getStatistics(),
keepalive: true
});
}
El método fetch() tiene la ventaja de un mayor control sobre lo que se envía al servidor. Lo que no muestro en el ejemplo es que fetch() también devuelve una promesa que se resuelve con un objeto Response. Como intento evitar la descarga de la página, decidí no hacer nada con ella.
SendBeacon()
SendBeacon()
usa la API de Fetch en segundo plano, 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 la descarga de una página. Su principal ventaja es su 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 los navegadores, XMLHttpRequest() esperamos que se quite
de la plataforma web. Los proveedores de navegadores están de acuerdo en que se debe quitar, pero llevará tiempo. Dar de baja uno de sus peores casos de uso es un primer paso que mejora la experiencia del usuario para todos.