¡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.
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
const CONNECTION = { crossDomain: true }
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.
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`)
}
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)
}
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
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.
¡¡ 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
y nuestro Error
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
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 !
var Ids = [1,2,3,4]
Es aquí donde se guardarán nuestras promesas.
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.
ya tenemos nuestro paquete de promesas… ahora queremos obtener los datos que nos interesan, en este caso el nombre.
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.
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)
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 !
¡Muchas gracias! Me está sirviendo mucho para repasar en orden los conceptos. Aunque una corrección: es *request no “reguest” 😉
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 😄.
Es request no “reguest”, significa petición.
información muy útil, lástima que la entiendo…
Muchas gracias compañero! Me ayudaste un montón
Te Felicito!!!
Gracias. Esto me está ayudando bastante como complemento a los vides.
#Excelente
Muy útil la información! Muchas gracias!