8

¡ENTENDIENDOLO TODO! reguests y promesas.

¡Hola amigas y amigos !
Sí tienes clara la función del Event loop y ya entiendes el asincronismo en JavaScript, entonces estás listo para enfentarte a los reguest, callbacks y promesas.

¿QUÉ ES un reguest ?
Es un pedido de información a determinada API, en donde se encuentran todos los datos ordenados, listo para ser utilizados.


INSTALAR jQuery
Tenemos que insertar esta librería desde nuestro HTML, este deberá estar antes de nuestro script

para hallar el script de inserción tenemos que ir a https://code.jquery.com y copiar el código de integración minificado

<scriptsrc="https://code.jquery.com/jquery-3.4.1.min.js"integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="crossorigin="anonymous"></script>

Ahora estamos listos para utilizar el método de jQuery que nos permite hacer un reguest

$.get(parametro1,parametro2,parametro3)

.get requeire tres parametros que explicaré en orden.


  • Parámetro#1 : Este deberá llevar la URL del API, en nombre de la tabla de datos(en este caso people/), y el id del objeto que queremos traer. cómo todo esto ocuparía almenos dos lineas de codigo y aún así sería poco legible, lo que haremos será separarlos en constantes
const API_URL = 'https://swapi.co/api/'

Para este ejemplo utilizaremos la API https://swapi.co

const PEOPLE_URL = 'people/:id'

ahora podemos juntar estos dos URL en una sola constante

var id = 1const URL = `${API_URL}${TABLE_URL.replace(':id', id)}`

.replace : reemplaza una parte de un string por otra


  • Parámetro#2 : será la configuración de dominio de nuestro reguest, en este caso indicaremos que es un API externa y que vamos a cruzar nuestro dominio con el de SWAPI
const CONNECTION = { crossDomain: true }
  • Parametro#3 : será la función/callback que se ejecutará en algún momento después de que el reguest sea exitoso
const onPeopleResponse = function(data){
 console.log(`Hola, soy ${data.name}`
}

¿QUÉ ES data ?
Resulta que un reguest trae varias cosas dentro de el, para saberlo podemos hacer un console.log de los argumentos que este tiene

const onPeopleResponse = function(data){
 console.log(arguments)
}


POR FIN estamos listos para invocar nuestro reguest !

$.get(URL,CONNECTION,onPeopleResponse)

Al ejecutar el reguest vamos a recibir los argumentos de este, son tres
pero el primero es el que nos interesa, la data.

arguments.PNG
Ahora sabemos cuales son los argumentos del objeto, y sus keys o características

const onPeopleResponse = function(data){
 console.log(`Hola, soy ${data.name} y mido ${data.height} centimetros`)
}
height.PNG

ENCAPSULAR reguest en una función
Vamos muy bien, ahora podemos hacer una función que funcione en base a que id nos de el usuario.
para eso utilizaremos un prompt()

var id = prompt('¿Qué id quieres buscar?')

functionobtenerPersonaje(id){
 const URL = `${API_URL}${PEOPLE_URL.replace(':id', id)`

 $.get(URL,CONNECTION,onPeopleResponse)
}

console1.PNG

Todo excelente hasta el momento …pero
¿QUÉ PASA cuando ocurre un error ?
Si ocurre algo inesperado que no permita la ejecución del reguest la consola nos mostrará este feo mensaje
errorget.PNG
Lo bueno de todo esto esque podemos hacer nuestro propio mensaje de ERROR, y para esto utilizaremos .fail()


.fail : Requiere una función como parametro, este será ejecutada cuando algo no permita la ejecución del reguest


function obtenerPersonaje(id){

 const URL = `${API_URL}${PEOPLE_URL.replace(':id', id)`

 $.get(URL,CONNECTION,onPeopleResponse)
	.fail( ()=>{//arrow function
	console.log(`Nose ha podido obtener el personaje ${id}`)
})
}

seguirán saliendo los dos mensajes, pero ahora el usuario tendrá una idea más clara de lo que ha pasado.
errorget2.PNG


¡¡ Y POR FIN LAS PROMESAS !!
Ahora si entenderás de una vez y por todas qué son las promesas y para qué funcionan.
¿QUÉ SON?
Son valores prometidos, qué al momento de declarar la función simplemente ANHELAMOS tener.
Para crear una nueva promesa es necesario comenzar la función con un return, lo cual hará que al momento en que la función se invoque, primero se tenga en cuenta a la promesa que estamos a punto de crear.

functionObtenerPersonaje(id){
	returnnewPromise( )
}

La promesa recibe como parámetro una función(en este caso una Arrow/function), que a su vez recibe el metodo resolve, y reject como parámetros.

functionObtenerPersonaje(id){
returnnew Promesa( (resolve,reject) =>{
	//CUERPO DE LA FUNCIÓN
}

¿QUÉ ES resolve y reject ?
Son las dos opciones de **resolución **de la promesa, para entender mejor esto, aprendamos los estados por los que puede pasar una promesa.

  • Pending: es el estado inicial de toda promesa

  • Fulfilled : una promesa pasa a este estado cuando se resuelve exitosamente

  • Rejected : cuando ocurre algún error.

teniendo esto claro, continuemos declarando nuestra función promesa…

functionObtenerPersonaje(id){
returnnew Promesa( (resolve,reject) =>{
	const URL = `${API_URL}${PEOPLE_URL.replace(':id', id)}`
	$
	.get(ULR,CONNECTION, function(data){
	resolve(data)
})
.fail( ()=> reject(id) )
}

¿QUÉ HA pasado aquí ?

  • Como tercer parámetro de nuestro reguest vamos a declarar una función, la cual que va a tener como parámetro el dato que anhelamos tener, en este caso la DATA.
    Cuando esta función se ejecute, osea cuando nuestro reguest sea exitoso, se invocará el método resolve, enviándole el parámetro que necesita (data).

  • También declaramos una función (Arrow) que invoque al método reject pasando le como parámetro el id que no fue encontrado.
    De esta manera sabemos QUÉ hacer con la data antes de tenerla, ¿no es genial 😄?


PERO PERO PERO !
¿Qué harán exactamente resolve y reject con nuestra data ?
Pues la verdad es que aún no lo hemos declarado, esto lo tenemos que hacer al momento en que la función ObtenerPersonaje() se invoque. veamos cómo hacerlo

ObtenerPersonaje(id)
.then()
.catch()

con .then() y .catch() sabremos a qué estado paso nuestra promesa después de que el reguest se ejecute.

.then( función ) : ejecutará la función que le asignemos cuando la promesa pase a Fulfilled
.catch( función ) : ejecutará la función que le asignemos cuando la promesa pase a Rejected

Ahora bien, sabiendo que nuestro dato prometido es DATA, declaremos una función que obtenga el data.name y haga un bonito saludo, la llamaremos onSuccess y sera la función que irá como parámetro en el .then

function onSuccess (data){
	console.log(`Hola, soy ${data.name}`)

Hagamos una para cuando algo raro ocurra !

functiononError(id){
console.log(`No se pudo obtener el personaje ${id}`)
}

está función recibe el mismo id de reject(id), que a su vez en el mismo id que nos permite buscar un personaje en especifico.
AHORA SI ESTA TODO LISTO !
sólo nos falta llamar a las funciones que acabaos de crear como parámetro dentro de .then y .catch

ObtenerPersonaje(id)
.then(onSuccess)
.catch(onError)

nuestro Success
Captura.PNG
y nuestro Error
Captura2.PNG
Ahora que entendemos cómo hacer una promesa, es hora de aprender cómo hacer múltiples promesas en cadena. Para lograr esto usaremos de nuevo el return justo antes de que la función/parámetro (onSuccess) termine.

Declararé la función dentro del .then, para hacerlo más visible.

ObtnerPersonaje(1)
.then( function(data) =>{
	console.log(`Hola, soy ${data.nam}`)
return ObtenerPersonaje(2)
}

Ahora bien, ¿a dónde va la función ObtenerPersonaje(2)?
Es la promesa que será escuchada justo después de la actual, ahora sólo hará falta obtener la resolución de esta nueva promesa con un nuevo .then

ObtnerPersonaje(1)
.then( function(data) {
//primera prosemaconsole.log(`Hola, soy ${data.name}`)
	return ObtenerPersonaje(2)
}).then(function(data) =>{
//segunda promesaconsole.log(`Hola, soy ${data.name}`)
	return ObtenerPersonaje(3)
}).then(onSuccess)
//tercera y ultima promesa
.catch(onError)
//promesa de error

Captura4.PNG
y listo ! tenemos nuestras promesas encadenadas, pero…


¿no sería mejor OBTENERLAS EN PARALELO?

Para lograr eso tenemos que hacer algo un poco diferente. Vamos a verlo !

  • Lo primero que necesitamos es un array que contenga la cantidad de Ids que queremos buscar
var Ids = [1,2,3,4]

Captura5.PNG
Es aquí donde se guardarán nuestras promesas.

  • Es hora de empaquetar nuestras promesas dentro del array, para ello utilizaremos .map() que nos devolverá un nuevo array modificado con la función que le pasemos por parámetro.
var promesas = IDs.map( (id)=> ObtenerPersonaje(id) )

¿QUÉ HA PASADO AQUÍ ?
El arrow function que está dentro del .map bien podría llamarse invocar promesa, pues en realdiad es lo que hace a partir del id que en este caso equivale al numero de cada objeto dentro del array.

Captura6.PNG
ya tenemos nuestro paquete de promesas… ahora queremos obtener los datos que nos interesan, en este caso el nombre.

  • Haremos una función que sepa cuantos objetos hay dentro de nuestro Arry promesas, y que además resuelva cada una de lás promesas utilizando los datos que nos interesan.
functionObtenerPersonajeS(personajes){

for (var i = 0; i < personajes.length; i++{
var nombre = personajes[i].name
console.log(`Hola, soy ${nombre}`)

 }
}

¿QUÉ HA PASADO AQUÍ?
El ciclo for cuenta los objetos dentro del array pasado por parametro(personajes), y obtiene el dato .name de cada uno de los obtejos para hacer un saludo.

  • Sólo nos resta utilizar nuestro array de promesas dentro del método Promise.all() el cual ejecuta todo un array de promesas como si fuera una sola, internamente lo que hace es esperar a que todas las promesas se resuelvan para luego resolverse a si misma.
Promise
.all(promesas).then( personajes => ObtenesPesonajeS(personajes) ).catch(onError)

¿QUE HA PASADO AQUÍ?
El parametro de .all es nuestro Array, luego cuando nuestras promesas se hagan realidad tomarán el nombre de personajes que es otro array, con el cual funciona nuestra función ObtenerPersonajeS().
Si algo raro llega a pasar declaramos tambien nuestro catch(onError)Captura7.PNG
y Listo ! tenemos nuestras promesas en paralelo, pero …


Tenias que llegar hasta aquí para entender la manera más simple de Dominar el uso de promesas con Async-await.
Async-await nos permite declarar una función asíncrona la cual deberá esperar a que un conjunto de promesas se cumpla para terminar de ejecutarse. Así se ve el codigo

asyncfunctionObtenerPersonajesPRO(){
try{ 
var personajes = awaitPromise.all(promesas) 
}
catch(id){
onError(id)
}

¿QUÉ HA PASADO AQUÍ?
Dentro de la ejecución del try, la variable personajes es un array que está esperando a que todas las promesas dentro del array promesas pasen a un estado de fulfilled.
El parametro que recibe el catch es el mismo del rejected declarado en las promesas, dentro de la ejecución del catch se invocará el onError().


Esto tiene el mismo funcionamiento de la función anterior, sólo que esta vez utilizamos una metodología más avanzada para logararlo, el truco está en tendender todos estos conceptos a la perfección ya que cuando lleguemos a frameworks como ReactJs el uso de promesas será muy frecuente.

Y a seguir aprendiendo, que lo que nos queda es camino !

Escribe tu comentario
+ 2
2
1284Puntos

¡Muchas gracias! Me está sirviendo mucho para repasar en orden los conceptos. Aunque una corrección: es *request no “reguest” 😉

1
2261Puntos
5 días

Iba a hacer la misma aclaración ya que “request” significa “petición”, es decir, una solicitud que le haces al servidor para que te brinde unos datos 😄.

1
1897Puntos

Gracias. Esto me está ayudando bastante como complemento a los vides.