Actualmente desarrollo plugins para WordPress, y recién me topé con algo que nunca había pensado: “Enviar peticiones AJAX antes de que el usuario cierre nuestra página web“.

Antes de empezar este post, dejemos claro dos cosas:

  1. Lo que veremos a continuación será completamente JavaScript.
  2. El problema anterior puede ser enfocado a cualquier tipo de aplicación web, no solo para WordPress.

Indagué por la web

La mayoría de las respuestas a mi problema provenían de StackOverflow, y mi sorpresa fue que, no soy el único buscando lo mismo.

Hasta hace unos años, varias personas recomendaban usar el siguiente método:

  • Realizar peticiones síncronas.

El problema es que esto provoca que el navegador o la pestaña tarden un poco en cerrar, debido a que la petición aún se sigue ejecutando.

Sin embargo, en años más recientes, hubo una persona que comentó dos palabras:

Beacon API

¡Ésta es la solución! Me dije.

¿Por qué? Pues, se veía sencillo de usar y su documentación decía lo que yo quería hacer en ese momento. Y lo logré.

Un resumen de lo que dice su documentación:

La Beacon API es usada para realizar peticiones asíncronas y no bloqueables a un servidor web. Aborda las necesidades de ejecutar código que intenta enviar datos al servidor web antes de que el documento se cierre.

La documentación lo explica sencillo, y el código mucho más; pero antes de seguir, me gustaría explicar que es una petición AJAX.

¿Qué es una petición AJAX?

Al principio de mi carrera, el hacer uso de algo llamado AJAX en mis desarrollos, era algo tenebroso. Tal vez para ti, mi querido lector, también lo fue.

¡No le tengas miedo! De hecho, creo que fue una de las mejores cosas que pude haber conocido, y lo mejor que le pasó a la web.

AJAX significa JavaScript Asíncrono y XML, y nos sirve prácticamente para:

  • Obtener datos de un servidor web sin recargar la página.
  • Enviar datos a nuestro servidor sin que el usuario se vea interrumpido.

Hacer uso de AJAX hoy en día es totalmente normal, y lo puedes implementar con varias tecnologías, ya sea usando VanillaJS, jQuery u otros.

A continuación, te dejo un video de Platzi para una mejor comprensión del tema:

¿Qué es AJAX y cómo funciona? – Por Platzi

Compatibilidad

Antes de empezar a trabajar con la Beacon API, hay que tener en cuenta que, en este año 2018, esta API es compatible en la mayoría de los navegadores, a excepción de Internet Explorer y Opera Mini:

Compatibilidad de la Beacon API
Imagen 1. Compatibilidad de la Beacon API entre navegadores.

Usando la Beacon API

Pero volvemos al principio del problema:

Enviar peticiones AJAX antes de que el usuario cierre nuestra página web.

La Beacon API nos provee la siguiente función:

navigator.sendBeacon( url, data );

Esta función nos permite enviar los datos que queremos transmitir a nuestro servidor antes de cerrar nuestra página.

Acepta dos parámetros:

ParámetroDescripción
urlÉsta será la URL a donde queremos transmitir los datos.
dataEste es una variable que contendrá los datos a enviar en la petición.

Cabe destacar que, el tipo de la variable a enviar debe ser:

Cualquiera de éstos tipos es aceptable, escoge el que más te convenga. Sin embargo, en los siguientes ejemplos usaremos FormData.

Ahora, la pregunta del millón, ¿cómo lo usamos para enviar datos antes de cerrar nuestra página web?

Bien, tenemos que usar un evento de JavaScript llamado unload, éste se ejecuta justo antes de que la página sea cerrada o recargada:

window.addEventListener( 'unload', sendData, false );

Cuando la página sea cerrada, se ejecutará la función sendData:

function sendData() {
var formData = new FormData();
var currentTasks = getSomeTasks();
 
if ( Object.keys( currentTasks ).length <= 1 ) {
return;
}
 
formData.append( 'action', 'cronjob_task_system' );
formData.append( 'currentTasks', JSON.stringify( currentTasks ) );
 
navigator.sendBeacon( myObject.url, formData );
}

Primero, tenemos que hacer una instancia de FormData, ó cualquier tipo de variable que mencionamos anteriormente, y agregar los datos que queremos enviar a nuestro servidor.

Puedes hacer cualquier operación antes de enviar los datos, por ejemplo, yo en el código digo que si mi variable currentTasks está vacío, no envíe nada al servidor.

¿Por qué mi código está en inglés? Chécalo en mi post sobre ¿por qué es necesario nombrar bien las cosas en programación?

Ya que la lógica esté lista, pasamos los respectivos parámetros a navigator.sendBeacon( url, data ) y manejamos esos datos en nuestro servidor.

Inconvenientes

El uso de la Beacon API es impresionante, cumple con nuestros objetivos al querer enviar datos al servidor cuando la página se haya cerrado; sin embargo, existe un inconveniente.

Si queremos implementar la Beacon API, dijimos que tenemos que ejecutarlo en el evento unload, ¿verdad?

Sin embargo, este evento se ejecuta no sólo cuando la página es cerrada, si no que también se ejecuta cuando el usuario recarga la página, o cuando el usuario cambia de página dentro del mismo dominio.

Tal vez sea un inconveniente o no, depende del tipo de proyecto que estés desarrollando.

Posible solución a los inconvenientes

Como dije, la Beacon API tendrá sus inconvenientes o no, dependiendo del tipo de proyecto que estés desarrollando, por ejemplo, si quieres enviar datos estadísticos de las partes donde navegan tus usuarios, éste método es perfecto.

Pero si andas buscando algo que únicamente se ejecute al cerrar la página, tal vez tengas que usar algo parecido al Heartbeat API de WordPress, para que tu servidor se comunique si el usuario sigue en tu página o no.

Conclusión

La verdad es que, el uso de la Beacon API me ha salvado de implementar demasiado código en el proyecto que estaba desarrollando, y espero que te pueda servir a ti también.

Sin embargo, el uso del evento unload, es algo que debe mejorarse para solucionar los inconvenientes que previamente mencionamos.

¿No te ha funcionado la implementación del código? Deja un comentario y con gusto te apoyo.

0

Escrito por Roel Magdaleno

Desarrollador Backend y Performance Engineer.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *