Aprovecha el precio especial.

Antes:$249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

14d

12h

47m

56s

375

Las promesas y async await lógicamente no son iguales. Y te explico el porqué.

David
davos_
29533

¿Alguna vez te has preguntado el por qué existe async await si ya se tiene las promesas? Muchos desarrolladores ya están usando esta funcionalidad. Sin embargo, no saben cómo funciona o cómo es diferente de las promesas. Eso es exactamente lo que abarcará este post. Empezaremos recordando por qué llegaron las promesas y cómo es que funciona, luego será el turno de async await y su funcionamiento. Finalmente veremos un ejemplo de cómo aplicar estas dos formas de manejar la asíncronia en conjunto.

  • ¿Por qué Promesas?
  • La llegada de Async Await
  • Async Await y Promesas trabajando juntos

Para poder entender varios términos que se va a usar, es necesario tener cierto conocimiento previo de Javascript y su asíncronia. Por eso, te recomiendo leer estos posts. Son muy buenos!

Ya tenemos todo lo necesario y ya estás listo para seguir leyendo este post. Esta es una oportunidad de entender mejor la asíncronia en Javascript. A por ello!

Alt Text

¿Por qué Promesas?

Las promesas llegan en ECMAscript 2016 como solución a uno de los problemas que generaba los callbacks, el callback hell. Este hacía que el código asíncronico se apile horizontalmente a la derecha. Por lo cual esto hacía que el código se vuelva muy complicado de leer. Lo que planteaba las promesas era una mejor sintaxis. En vez de que el código esté horizonal, pues que esté vertical y encadenado. Veamos un ejemplo para entenderlo mejor.

En estos trozos de código hacemos unas llamadas a un api para conseguir el id de un usuario, conseguir sus seguidores y haces más cosas. Haciendo esto con tan solo callbacks, nos resulta como en la imagen. Imagínate que haya muchos más callbacks. ¿Difícil de leer, no?

    callEndpoint('api/getidbyusername/davos', function (results) {
    	callEndpoint('api/getfollowersbyid' + results.userId, function (results) {
    		callEndpoint('api/someothercall', function (results) {
    			callEndpoint('api/someothercall', function (results) {
    				callEndpoint('api/someothercall', function (results) {
    					callEndpoint('api/someothercall', function (results) {
    					// do things here
    					})
    				})
    			})
    		})
    	})
    })

Pero con las promesas todo es diferente, el código se vuelve vertical y más legible.

    callEndpoint('api/getidbyusername/davos')
    	.then(results => callEndpoint('api/getfollowersbyid' + results.userId))
    	.then(results => callEndpoint('api/someothercall'))
    	.then(results => callEndpoint('api/someothercall'))
    	.then(results => callEndpoint('api/someothercall'))
    	.then(results => callEndpoint('api/someothercall'))

Entonces, ¿Las promesas es solo sintaxis y funcionan igual que los callbacks?

No exactamente. Es cierto que las promesas manejan código que será ejecutado en algún futuro al igual que los callbacks. Nótese aquí la incertidumbre de cuándo será ejecutado este código. Sin embargo, la diferencia está en el mecanismo de las promesas. Pero antes, repasemos un poco para entender este mecanismo. El código síncrono inmediatamente se va a un lugar llamado el Call Stack, aquí la última función que entra al stack es el primero que se ejecuta y que sale del stack así hasta la primera que ingreso. Por otro lado, el asíncrono se va a una cola de tareas para su respectiva ejecución. Una vez que el Call Stack esté vacío, el Event Loop moverá las funciones que ya estén listas de la cola de tareas al Call Stack y luego pasarán a mostrar su resultado. Con esto en mente retomemos las promesas. Estas se dirigen a una cola de tareas diferente a las que van los callbacks. Los callbacks se van al Task Queue y las promesas al PromiseJobs o también llamado MicroTask Queue. Estos son manejadores de tareas, básicamente son los que deciden qué funciones son las que entran y las que salen.

https://miro.medium.com/max/771/1*CUyECMl99NBj7PurcEUwVg.jpeg

Referencia: https://medium.com/@jitubutwal144/javascript-how-is-callback-execution-strategy-for-promises-different-than-dom-events-callback-73c0e9e203b1

Si te has confundido o si aún así quieres saber un poco más de los Tasks, MicroTasks y queues, te dejo este post muy bueno para profundizar estos conceptos.

Tasks, microtasks, queues and schedules

Ahora ya tenemos una idea de cómo funciona las promesas. ¿Y async await? Pues vamos a ello.

La llegada de Async Await

En ECMAscript 2017 es cuando Async Await entra al juego. Este nuevo feature de Javascript planteaba un mejor manejo de las promesas. Estos ya no estarían encadenados uno del otro volviendo la sintaxis más entendible y fácil de usar. Sobre todo fácil de usar. Para usarlo tan solo se necesita async functions y la keyword await. Este keyword permite que una promesa se resuelva y retorne su valor, esto permite que podamos guardarlo en variables. Pero no todo podía ser oro. await solo funciona en async functions. Este tipo de funciones simplemente se aseguran que lo que sea que retornen sea una promesa. Dicho de otro modo, estas funciones siempre retornan una promesa. Veámoslo en un ejemplo.

Tomaremos el ejemplo de las promesas y convertiremos su sintaxis usando async await

// usando Promesas
    callEndpoint('api/getidbyusername/davos')
    	.then(results => callEndpoint('api/getfollowersbyid' + results.userId))
    	.then(results => callEndpoint('api/someothercall'))
    	.then(results => callEndpoint('api/someothercall'))
    	.then(results => callEndpoint('api/someothercall'))
    	.then(results => callEndpoint('api/someothercall'))
    
    // usando Async AwaitasyncfunctioncallEndpoints() {
    	const userResults = await callEndpoint('api/getidbyusername/davos')
    	const followersResults = await callEndpoint('api/getfollowersbyid' + userResults.userId)
    	const someResults = await callEndpoint('api/someothercall')
    	const moreResults = await callEndpoint('api/someothercall')
    	const anotherResults = await callEndpoint('api/someothercall')
    	const finalResults = await callEndpoint('api/someothercall')
    
    	return finalResults
    }

    callEndpoints()

Después de ver la sintaxis creo que estamos de acuerdo que es mucho más simple y entendible de usar. Sin embargo, el manejo de async await es diferente a la de las promesas. Sabemos que await hace una pausa hasta que la promesa se resuelva. Literalmente, hace que la ejecución del async function espere hasta que la promesa se resuelva y retorne un valor, aúnque esto no detiene el engine del lenguaje, este aún puede ejecutar otros scripts o eventos, esto significa que está volviendo el código asíncrono en síncrono. Y tal vez habrás pensado en qué sentido tiene esto si ya no va a ser asíncrono o no sea de utilidad y que mejor sigues trabajando con las promesas. Pues, esto no es totalmente cierto. Async Await puede brillar en ciertos casos de uso donde necesitemos esperar y saber cuándo alguna función asíncrona se ejecute, por ejemplo en el caso de pedidos a una api, donde necesitemos que primero la página se llene de datos para que el usuario pueda interactuar.

Pero, y si te dijera que podemos ir aún más allá y combinar lo mejor de ambos mundos. Podemos aprovechar la pausa de async await y las utilidades de las promesas como Promise.all . Esto lo veremos en el siguiente tema en un caso de uso donde sean necesario tener ambas.

Async Await y Promesas trabajando juntos

Vamos a suponer que estamos programando una carga inicial del perfil de usuario y que uno de los requerimientos sea que debamos mostrar la información básica del usuario, los cursos que ha tomado en la plataforma y la lista de sus amigos antes de que termine la carga. Estos recursos se consiguen por medio de una api, y cada recurso está en una diferente url. Y las url del api de los cursos y la de amigos vienen en la información del usuario en la propiedad links.

  • Información del usuario: api/user/1234
  • Cursos que ha tomado: api/user/1234/courses
  • Lista de sus amigos: api/user/1234/friends

Este es un ejemplo de la respuesta a un pedido a la url de la información del usuario

    {
    	user: {
    		id: 1234,
    		...
    		links: ['api/user/1234/courses', 'api/user/1234/friends']
    	}
    }

Entonces tenemos que hacer 3 pedidos a la api y debemos tener acceso a su data antes de que termine la carga. Está claro lo que debemos usar, async await y promesas.

Vamos a crear una async function donde en primera instancia haremos un pedido a la url del usuario para obtener la información básica y los links que están como propiedad del usuario. Luego, usaremos una utilidad de las promesas, Promise.all. Esto hará que los pedidos se ejecuten paralelamente, por lo tanto el tiempo de espera se disminuye al no tener que ejectuar los pedidos de los links consecutivamente. Un detalle es que si alguno de estos pedidos falla en el Promise.all, todos fallarán. O todo o nada.

Dentro de Promise.all, iteraremos sobre los links con la función de los arreglos, map . Este recibe una función que tiene como argumento el elemento del arreglo en cada iteración, en este caso el link. Luego dentro de la función, aplicamos un arrow function que retorna un fetch al link en cada iteración. Esto hará que en cada iteración se retorne una promesa. Al final, tendremos un arreglo de estas promesas sin resolver. Para esto aplicamos await al Promise.all para que resuelva todas las promesas paralelamente. Una vez ya resueltos, obtendremos todas las respuestas de los pedidos si todo fue bien y lo guardamos en una variable userResponse. Por último aplicamos todo esto de nuevo para parsear las respuestas en data de tipo objeto para que Javascript pueda hacer operaciones sobre la data.

asyncfunctiongetAllUserInfo(id) {
    	const user = await fetch('api/user/' + id)
    
    	const userResponse = awaitPromise.all(user.links.map(link => fetch(link)))
    
    	const userData = awaitPromise.all(userResponse.map(response => response.json()))
    
    	return userData
    }

Por último obtenemos la data requerida para el usuario, y logramos hacer que la información se visualice por el usuario final.

Conclusión

Para resumir, las promesas y async await resuelven la asincronía de distinta forma. Con las promesas no sabemos cuándo se va a resolver y con async await forzamos una espera en la función. No siempre se va a usar uno, el otro o ambos, por ello lo primero es entender el caso de uso y después empezamos a implementar todo lo que hemos aprendido aquí.

Escribe tu comentario
+ 2
Ordenar por:
12
9641Puntos
5 años

Buen post recopilando todo, sencillo de entender y con una aplicación directa a cada cosa

3
29533Puntos
5 años

Gracias por el feedback!

5
61853Puntos
4 años

Tendré que volver luego de ver unos cuantos videos mas en YouTube porque me esta costando un poco entender cuando se usan al mismo tiempo, trabajando juntos.

2
6805Puntos
3 años

gracias por el aporte, entiendo mejor acerca del uso de las api’s y la necesidad de usar asincronía en nuestros proyectos que muchas veces son síncronos, pues, buen punto, muchas gracias, Dios los bendiga Platzi.

2
8738Puntos
4 años

Gracias por el aporte, aun no me queda claro del todo pero espero que con la practica pueda tomarle el sentido…

2
8261Puntos
5 años

Muchas gracias por compartir

1
29533Puntos
5 años

Me alegro que te sirva, Pamela. 😃

2
19773Puntos
5 años

Uff que gran post, muchas gracias bro.

2
22868Puntos
5 años

Excelente tu post!!

1
29533Puntos
5 años

Gracias!

1
7180Puntos
2 años

Este post me vino de 10! muy buen aporte! muchas gracias!!

1
5774Puntos
2 años

No entiendo muy bien cual es la utilidad de que se ejecuten de manera paralela si la entrada de uno es la salida de otro

1
16954Puntos
3 años

usi que he disfrutado este platzi day saludos gracias

1
1524Puntos
3 años

Excelente aporte!!

1
3499Puntos
3 años

Excelente post, sirve mucho para entender la diferencia.

1
7024Puntos
3 años

Muy buen post, lo agregó a mis apuntes. Gracias!

1
28159Puntos
3 años

Veo este aporte de nuevo, porque es excelente!

1
8138Puntos
3 años

Muchas gracias por compartir este post, me aclaró algunas dudas

1
5378Puntos
3 años

Está Genial !! muchas gracias

1
3843Puntos
4 años

excelente

1
10768Puntos
4 años

Muy buen post!

1
13670Puntos
4 años

Estoy haciendo el curso de fundamentos de JS y me vine a este post para entender de manera mas clara sobre async await. Muchas gracias por ponerlo en palabras tan claras y de fácil comprensión.

1
22190Puntos
4 años

Gracias por este gran post!, de gran utilidad.

1
10084Puntos
4 años

Muchas gracias me has hecho entender mejor, las promesas y las async await

1
19434Puntos
4 años

Interesante, me aclaró algunas dudas, pero debo seguir profundizando más en este tema.

1
4 años

Es excelente el post, realmente jamás me había puesto a pensar sobre todo esto, pero es algo que sirve de mucho.

1
72686Puntos
4 años

Gracias, me ayudo a entender un poco más.

1
8059Puntos
4 años

Me encantó como pones las diferencias entre los tres, citando referencias. La verdad me ayuda mucho a tener en mi cabeza la diferencia específica. Gracias!!

1
13858Puntos
4 años

Excelente el post, interesante, conciso y directo.

1
31152Puntos
4 años

Increíble post, algo así estuve buscando para comprender como trabaja Async await y de que forma los interpreta el Engine.

1
19205Puntos
4 años

Uno de los mejores y más completos posts que he visto en platzi. Infinitas gracias por esta gran contribución!

0
4 años

Excelente que buena información, lo mejor de todo es que fue con un ejemplo real, lo cual ayuda a dejar el concepto mucho mas claro

0
30861Puntos
4 años

Hola,

Esta Re_bien la explicación, ahora queda practicar!

Gracias.

0
8116Puntos
4 años

Muchas gracias!. Si que me ayudo a entender mejor este tema.

0
48906Puntos
4 años

Me huele a que tendría mucha utilidad en formularios con mucho UX donde una pregunta no pueda ser ejecutada si no se resuelve otra antes, y en exámenes virtuales, como los de Platzi. Diganme si estoy por ahi en lo cierto. o No? 😦 jaja