Estos días he visto que muchos desarrolladores no tienen tan clara la idea de cómo manejar procesos asíncronos, en concreto hacer peticiones HTTP a un servidor con Javascript, así que les hablaré un poco acerca de AJAX.
¿Qué es una petición HTTP?
Una petición HTTP es como suele denominarse a la acción por parte del navegador de solicitar a un servidor web un documento o archivo, ya sea un fichero .html, una imagen, una tipografía, un archivo .js, etc. Gracias a dicha petición, el navegador puede descargar ese archivo, almacenarlo en un caché temporal de archivos del navegador y, finalmente, mostrarlo en la página actual que lo ha solicitado.
¿Qué es AJAX?
Comencémonos con dos conceptos para un proceso en javascript:
- Síncrono: Es un proceso que se ejecuta al mismo tiempo que los demás.
- Asíncrono: Es un proceso que se ejecuta a destiempo de los demás.
Citando a la MDN. “JavaScript Asíncrono + XML (AJAX) no es una tecnología por sí misma, es un término que describe un nuevo modo de utilizar conjuntamente varias tecnologías existentes. Esto incluye: HTML o XHTML, CSS, JavaScript, DOM, XML, XSLT, y lo más importante, el objeto XMLHttpRequest.”
Pero… ¿Entonces solo puedo usar XML para hacer una transferencia de datos de servidor a cliente y viceversa? La respuesta es no, XML es un meta-lenguaje que se utilizaba en los inicios de AJAX para representar información estructurada, en la actualidad comúnmente se utiliza JSON es un poco más simple, sin embargo, también se manejan diferentes tipos tecnologías en esta transferencia de información.
Bien ya vimos conceptos y en si lo que representan, pero quizá sigas con las mismas dudas, ¿Por qué? O ¿Para qué?, te lo mostraré con una representación gráfica.
Representación de petición síncrona y asíncrona
Como se puede ver en la imagen una petición síncrona se envía y queda a la espera de la respuesta del servidor, posteriormente procesa la respuesta y continua cualquier proceso. Esta práctica incluso ya es deprecada debido a que no es una causa una buena experiencia de usuario y en algunos casos bloqueamos el “Event-Loop” tema al cual le dedicaré un post.
En la misma imagen vemos como se ejecuta una petición asíncrona la cual se realiza y posterior a ella se pueden ejecutar “n” numero de procesos debido a que no sabemos cuánto tiempo se demorará el servidor en responder, lo cual nos permite ejecutar otros procesos y cuando responde entonces realizamos el procesamiento de esa información con esta práctica evitamos el bloqueo del “Event-Loop” y mejoramos la experiencia de usuario al no bloquear el sitio.
Entonces como diría Linus Torvalds.
Talk is cheap. Show me the code…
Primero crearemos una estructura muy simple de HTML.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AJAX</title>
</head>
<body>
<strong>Hola esta es una lista de pokémon</strong>
<ol id="pokemons"></ol>
</body>
<script src="./app.js"></script>
</html>
Como lo ven crearemos una lista de Pokémon usaremos el recurso de https://pokeapi.co. Ahora dentro de esta estructura vemos como llamamos a un script llamado app.js el cual contendrá lo siguiente.
Primero lo más simple, crearemos una función que pueda llenar en base a un arreglo nuestra lista
function fillList(pokemons) {
let list = document.getElementById('pokemons');
pokemons.forEach(pokemon => {
let li = document.createElement('li');
li.appendChild(document.createTextNode(pokemon.name));
list.appendChild(li);
});
}
También crearemos la función que ejecutará la petición al recurso de pokeapi.
function request(async) {
console.log('Petición a servidor');
let req = new XMLHttpRequest();
req.open('GET', 'https://pokeapi.co/api/v2/pokemon?limit=50&offset=200', async);
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4) {
if(req.status == 200) {
let response = JSON.parse(req.responseText);
fillList(response.results)
console.log('Proceso de respuesta');
} else {
console.log('Error loading page');
}
}
};
req.send(null);
}
Como se puede ver esta función contiene un parámetro el cual es “async”, por medio de este le diremos si la petición es asíncrona o no, para poder probar lo que se explica en el diagrama. Y por último crearemos un evento el cual al cargarse todo el contenido de la página se ejecute.
document.addEventListener('DOMContentLoaded', function(event) {
console.log('Proceso 1');
request(false);
console.log('Proceso 2');
});
Ahora vamos a hacer pruebas, en esta primera prueba debido a que la petición no es asíncrona el resultado que nos tiene que dar en consola es:
Proceso 1
Petición a servidor
Proceso de respuesta
Proceso 2
Lo cual es correcto, pero como ya se explico no es lo más recomendable. Vamos a lo que nos interesa un poco más la petición asíncrona, el resultado de esta nos tiene que dar lo siguiente:
document.addEventListener('DOMContentLoaded', function(event) {
console.log('Proceso 1');
request(true);
console.log('Proceso 2');
});
Proceso 1
Petición a servidor
Proceso 2
Proceso de respuesta
El proceso 2 representa “n” procesos que se podrían ejecutar antes de que el servidor nos responda lo cual nos da muchas posibilidades las cuales solo serán limitadas por nuestra imaginación. También por ultimo el resultado de ambas peticiones dentro de la pagina es el listado de los Pokémon como se puede ver en la siguiente imagen.
En este ejemplo utilizamos el objeto “XMLHttpRequest” pero también existe “Fetch API” y algunas otras librerías que son algo interesantes, te invito a que las explores.
Conclusión
AJAX es una herramienta que nos ayuda bastante en la actualidad a reducir significativamente el tráfico de red y los tiempos de carga para brindarle al usuario una mejor experiencia en nuestros sitios.