Ya vimos el uso de callbacks para hacer requests a API’s, ahora veremos una implementación “más limpia” con promesas.
De la API queremos:
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:
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;
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! 🙋🏿♂️🖤