2

Requests a API’s con Promesas

Carlos
monoald
20133

Ya vimos el uso de callbacks para hacer requests a API’s, ahora veremos una implementación “más limpia” con promesas.

Objetivos

De la API queremos:

  1. Conocer el número de personajes que hay.
  2. El nombre del primer personaje.
  3. La dimensión del primer personaje.

Creando la promesa

Como lo hicimos con los callbacks necesitamos una función principal que ejecutara todos nuestros requests, para eso necesitaremos de nuevo nuestra dependencia XMLHTTPRequest, que se instala de la siguiente manera.

npm install xmlhttprequest --save

Instanciamos la dependencia en una variable.

let XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

Llamaremos a esta función igualmente fetchData, pero ahora solo tendrá un parámetro url_api. Usaremos el formato arrow function para nuestra función.

const fetchData = (url_api) => {
};

Como trabajamos con promesas, debemos retornar una nueva promesa, esta promesa ejecuta una función que recibe dos parámetros:

  • resolve: Este “enviará” el resultado exitoso según nuestra lógica.
  • reject: Este “envía” el error que pasó, según nuestra lógica.
const fetchData = (url_api) => {
	returnnewPromise( (resolve, reject) => {
	};
};

Dentro de la promesa creamos un nuevo elemento de la dependencia XMLHTTPRequest.

const fetchData = (url_api) => {
	returnnewPromise( (resolve, reject) => {
		const xhttp = new XMLHttpRequest();
	};
};

Con este elemento xhttp y su método abrimos una petición de tipo ‘GET’ a la URL de la variable url_api.

const fetchData = (url_api) => {
	returnnewPromise( (resolve, reject) => {
		const xhttp = new XMLHttpRequest();

		xhttp.open('GET', url_api, true);
	};
};

Ahora usaremos el método onreadystatechange para “escuchar” nuestra petición, usaremos un arrow function en esta

const fetchData = (url_api) => {
	returnnewPromise( (resolve, reject) => {
		const xhttp = new XMLHttpRequest();

		xhttp.open('GET', url_api, true);
		xhttp.onreadystatechange = () => {
		};
	};
};

Al escuchar la petición esperaremos que su “estado” sea igual a “4” (la petición termino) en una condicional. Anidaremos una condicional (ternario) que verificara el status de la petición, para saber si fue exitoso, en el atributo status podremos saberlo, únicamente debemos esperar que el status sea igual a “200” (exitoso).

const fetchData = (url_api) => {
	returnnewPromise( (resolve, reject) => {
		const xhttp = new XMLHttpRequest();

		xhttp.open('GET', url_api, true);
		xhttp.onreadystatechange = () => {
			if (xhttp.readyState === 4) {
	      (xhttp.status === 200)
			}
		};
	};
};

Si la petición fue exitosa, ejecutaremos el resolve y en caso contrario el reject. Para el resolve entregaremos un string parseado que podremos trabajar con él y para el reject generaremos un nuevo error que nos indique que paso.

const fetchData = (url_api) => {
	returnnewPromise( (resolve, reject) => {
		const xhttp = new XMLHttpRequest();

		xhttp.open('GET', url_api, true);
		xhttp.onreadystatechange = () => {
			if (xhttp.readyState === 4) {
	      (xhttp.status === 200)
				? resolve(JSON.parse(xhttp.responseText))
        : reject(newError('Error', url_api));
			}
		};
	};
};

Finalmente enviaremos esta petición.

const fetchData = (url_api) => {
	returnnewPromise( (resolve, reject) => {
		const xhttp = new XMLHttpRequest();

		xhttp.open('GET', url_api, true);
		xhttp.onreadystatechange = () => {
			if (xhttp.readyState === 4) {
	      (xhttp.status === 200)
				? resolve(JSON.parse(xhttp.responseText))
        : reject(newError('Error', url_api));
			}
		};
		xhttp.send();
	};
};

Exportaremos esta función del siguiente modo para poder usarla en un nuevo archivo.

module.exports = fetchData;

Ejecutando Promesas

Importaremos nuestra función de promesa del siguiente modo.

const fetchData = require('../directory');

Guardaremos la URL de la API que usaremos en una variable.

const API = 'https://rickandmortyapi.com/api/character/';

Y ahora pasaremos a ejecutar la promesa, enviando como argumento la API.

fetchData(API)

¡Alto! Ahora debemos añadir los elementos encadenados de las promesas (.then y .catch).

En la primera petición obtendremos un JSON que tiene el número de personajes en la API, y para acceder a él debemos entrar al atributo info que dentro tiene el atributo count, este último contiene el número de personajes, entonces lo imprimiremos.

fetchData(API)
	.then(data => {
  console.log(data.info.count) // 826
	})

¡Muy bien! Ya cumplimos nuestro primer objetivo, para cumplir el siguiente debemos llamar de nuevo a la función y entrar al primer personaje de la API. el argumento que enviaremos a fetchData será ${API}${data.results[0].id}como sabemos data es JSON y alberga muchos atributos, el resultado de entrar al atributo id del primer elemento ([0]) del elemento results nos devuelve este URL “https://rickandmortyapi.com/api/character/1” que es la “entrada” al primer personaje, para que podamos obtener su nombre y dimension.

fetchData(API)
	.then(data => {
	  console.log(data.info.count)
	  return fetchData(`${API}${data.results[0].id}`)
  })

Para capturar la nueva promesa encadenamos un nuevo .then al anterior e imprimimos el atributo name de nuestra nueva data que es el JSON del primer personaje.

fetchData(API)
	.then(data => {
	  console.log(data.info.count)
    return fetchData(`${API}${data.results[0].id}`) // 826
  })
  .then(data => {
	  console.log(data.name) // 'Rick Sanchez'
  })

Ya vamos 2/3, para conseguir la dimension se complica un poco, debemos entrar a otra “sección” de la API, por lo tanto, hacer una nueva petición. La URL de esta nueva sección se encuentra en el atributo url que está dentro del atributo origin del JSON de nuestro personaje “Rick Sánchez”.

Entonces pasamos este atributo como argumento de fetchData.

fetchData(API)
	.then(data => {
	  console.log(data.info.count)
    return fetchData(`${API}${data.results[0].id}`)
  })
  .then(data => {
	  console.log(data.name)
    return fetchData(data.origin.url)
  })

Capturamos esta nueva promesa con un último .then e imprimimos el atributo dimension del nuevo JSON.

fetchData(API)
	.then(data => {
	  console.log(data.info.count)
    return fetchData(`${API}${data.results[0].id}`) // 826
  })
  .then(data => {
	  console.log(data.name)
    return fetchData(data.origin.url) // 'Rick Sanchez'
  })
  .then(data => {
	  console.log(data.dimension); // Dimension C-137
  })

¡Lo logramos! Ya completamos todas nuestros objetivos. Únicamente falta encadenar el .catch para retornar un error en caso de que pase uno.

fetchData(API)
	.then(data => {
	  console.log(data.info.count)
    return fetchData(`${API}${data.results[0].id}`) // 826
  })
  .then(data => {
	  console.log(data.name)
    return fetchData(data.origin.url) // 'Rick Sanchez'
  })
  .then(data => {
	  console.log(data.dimension); // Dimension C-137
  })
	.catch(err => console.error(err));

Con esto terminamos, con las promesas podemos salvarnos del callback hell y no caer en él.

¡Saludos platzinauta, nunca pares de aprender! 🙋🏿‍♂️🖤

Escribe tu comentario
+ 2