Async/await - Funciones asíncronas

Funciones tipo async

El uso del objeto promise a veces pueda resultar algo complejo, sobre todo si estas acostrumbrado a programar solo rutinas sincronas: cada cosa en su momento y una depués de otra.

Existe una forma de suavizar o endulzar el uso de las promesas es el tandem formado por las funciones tipo async y el operador await.

¿Qué es una función async? Estrictamente hablando es una función que devuelve una promesa. Con esto ya nos ahorramos crear objetos promesas. Es muy fácil de usar: basta con anteponer la palabra async al principio de la declaración de la función

async function calcular(alto,base ){

var area = base*alto;

}

No es gran cosa ¿verdad? pero a partir de ahora podemos usar el objeto calcular() como una promesa. Podríamos asignarle la función resolve y reject a sendos métodos then()

, y seguir el código como cuando usamos promesas. Pero esto no ahorra mucho código ni lo aclara.

La potencia de esta forma de usar las promesas está en await, que como sabrás significa esperar, y eso es lo que hace un script cuando encuentra este operador: espera el resultado de una función.

Este operador no bloquea la ejecución del script, pero no devuelve ningún valor hasta que la función haya terminado de ejecutarse.

Lo mejor para ver como funciona es un ejemplo. Un script que simula una solicitud de presupuesto a un taller. El taller se toma su tiempo para dar una respuesta.

const tallerCalcular = function(){

     return new Promise(

     resolve => setTimeout( function(){

               const val = 200 + Math.trunc(Math.random() * 300);

               resolve(val+"Euros"); }, 2000 ));

};

async function pedirPpto() {

     let precio = await tallerCalcular(2000);

     return precio;

}

pedirPpto().then( (p)=>alert(p) );

for(i=0;i<2000; i++){ console.log(i) }; //el script continúa

Veamos con detalle como ha funcionado esto: la función tallerCalcular() representa la tarea del taller calculando el presupuesto. Cuando termine devolverá un valor, promete darnos un presupuesto dentro de un rato.

Ahora se declara la función tipo async, que como ves es una función normal, pero devolverá una promesa. En su cuerpo vemos el uso de await (solo se puede usar dentro de una función async) . Puedes leerlo como que el valor que se va a guardar en la variable presupuesto llegará más adelente y hay que esperar. Cuando lo tenga hará el return, pero ojo devuelve una promesa.

Así que cuando se resuleva la promesa entra en funcionamiento el método .then e invoca la función que actuará cuando se cumpla la promesa. En este caso una ventana alert con un mensaje.

Ves luego un bucle, lo he puesto para que veas que el bucle empieza a funcionar y no se para, el script sigue funcionando y en un momento dado aparece la ventana alert.

Para que veas la similitud he usado el método then, pero realmente no es necesario. Puede resolverse todo dentro de la función async

async function pedirPpto() {

    let precio = await tallerCalcular();

    alert(precio) ;
}

pedirPpto();

Pruébalo y verás que funciona exactamente igual. Observa la diferencia: en el primer caso es una forma digamos mixta la función se llama y se asigna al resultado el método then. En esta ocasión todo se resuelve dentro de la función async pedirPpto()

Este sistema permite que la programación asíncrona se vea un poco más como síncrona.

Notas

Las funciones tipo async son funciones que devuelven promesas.

Para comprender el uso de estas funciones es importante entender bien el funcionamiento de los objetos promise (las promesas)

El operador await espera un resultado de una expresión, lo normal es que esta expresión sea una promesa (promise), pero puede ser cualqueir función o expresión.

El operador await solo se puede usar dentro de una función async.

Aunque await espera a la resolución de una promesa, la ejecución del script no se bloquea.

El uso más sencillo de estas funciones sería algo así.

async function llamar(){

   var dato = await promesa();

   if(dato){

        ....

   }else{

        ....

    }

}

llamar();

Pero como devuelven promesas también se pueden usar los métodos then para gestionar la respuesta o los errores.

async function llamar(){

   var dato = await promesa();

   return dato

}

llamar().then(

    resolved (),

    rejected()

);

Aunque el manejo de errores en este tipo de funciones puede hacerse con el mecanismo try - catch. Facilita ver la programación asincorna como la sincrona.

async function llamar(){

   try

       var dato = await promesa();

       //aceptada

   catch{

       //bloque rechazada.... (error)

   }

}

llamar();

El sistema async/await es muy utilizado en las llamadas Ajax, o en el más moderno Fetch, utilizadas para que la página web pueda comunicarse con el servidor y recuperar datos desde él sin necesidad de recargar la página.