Async/Await como funcionan realmente: un ejemplo

Async/Await como funcionan realmente: un ejemplo
by Janeth Kent Date: 22-02-2019 async await promises callbacks javascript tutorial

Las Promises nos dan una manera más fácil de tratar secuencialmente la asincronía en nuestro código. Esta es una adición bienvenida, dado que nuestros cerebros no están diseñados para tratar eficientemente la asincronía. Las funciones Async/await, nos ayudan a escribir código completamente síncrono mientras realizamos tareas asíncronas en segundo plano.

La funcionalidad conseguida con las funciones asíncronas se puede recrear combinando promises con generators, pero las funciones asíncronas nos dan lo que necesitamos sin ningún código adicional del boilerplate.

Lo que veremos en este post

  1. Introducción (callbacks, promises, async/await)
  2. Ejemplos: Conversor de divisas que recibe datos asíncronos de dos API's. En este tutorial, vamos a construir una aplicación simple y útil que va a mejorar su conocimiento general de Async/Await.

Empezamos

Una nueva forma de escribir código asíncrono es Async/Await está basado en promises, así que no está bloqueando el flujo.

La gran diferencia es que el código asíncrono se parece y se comporta un poco más al código síncrono. Aquí es donde reside todo su poder.

Las opciones anteriores para el código asíncrono eran callbacks (llamadas de retorno) y promises.

Callbacks en acción

setTimeout(() => {
  console.log('This runs after 1000 milliseconds.');
}, 1000);

Problemas con callbacks El infame infierno de la devolución de llamada

Las llamadas de retorno de anidación dentro de las llamadas de retorno pronto comenzarán a verse así:

asyncCallOne()) => {
  asyncCallTwo()) => {
    asyncCallThree()) => {
      asyncCallFour()) => {
        asyncCallFive()) => {
          asyncCallSix()) => {
            asyncCallSeven()) => {
              asyncCallEight()) => {
                 asyncCallNine()) => {
                    asyncCallTen()) => {
                     //do something here
                    })
                  })
                })
              })
            })
          })
        })
      })
   })
})    

El infierno Callback

El escenario en el que las llamadas de retorno están anidadas en varios niveles en otras llamadas de retorno, lo que puede dificultar la comprensión y el mantenimiento del código.

 

Promises (promesas) en acción

const promiseFunction = new Promise((resolve, reject) => {
  const add = (a, b) => a + b;
  resolve(add(2, 2));
});
promiseFunction.then((response) => {
  console.log(response);
}).catch((error) => {
  console.log(error);
});

PromiseFunction devuelve una Promise que representa el proceso de esta función. La función de resolución señala la instancia de promesa cumplida.

Después, podemos llamar a .then() y .catch() en esa función promise:
then — Ejecuta una llamada de retorno que usted le pasa cuando la promesa ha terminado.
catch — Ejecuta una devolución de llamada que le pasas cuando algo sale mal.

 

Funciones Async (asincronas)

La función Async nos proporciona una sintaxis limpia y concisa que nos permite escribir menos código para conseguir los mismos resultados que prometemos.

Las funciones de asincronía se crean preparando la palabra async antes de la declaración de función de este modo:

const asyncFunction = async () => {
  // Code
}

Las funciones asíncronas se pueden pausar con la espera, la palabra clave que sólo se puede utilizar en una función de sincronización. Await devuelve lo que sea que devuelva la función de asíncrono cuando esté hecho. Esta es la verdadera diferencia entre promises y async/await:

// Async/Await
const asyncGreeting = async () => 'Greetings';
// Promises
const promiseGreeting = () => new Promise(((resolve) => {
  resolve('Greetings');
}));
asyncGreeting().then(result => console.log(result));
promiseGreeting().then(result => console.log(result));

Async/Await se parece al código síncrono, y el código síncrono es mucho más fácil de entender.

Vamos a seguir con un ejemplo, como mencionamos antes, vamos a construir un Convertidor de Moneda

Conversor de divisas

Aclaración y puesta en marcha del proyecto

El programa incluirá el código de la moneda de la que queremos convertir y el código de la moneda a la que queremos convertir, así como la cantidad de dinero. El programa genera entonces el tipo de cambio correcto basado en los datos de la API.

En esta aplicación vamos a recibir datos de dos fuentes asíncronas:

  1. Currency Layer — Necesitarás registrarte gratuitamente para poder usar la función API Access Key.
  2. Rest Countries — Esta API nos dará información sobre dónde podemos usar la moneda a la que acabamos de convertir nuestro dinero.

Vamos a crear un nuevo directorio y ejecutar npm init, saltar a través de todos los pasos, e instalar axios escribiendo npm i --save axios. Cree un nuevo archivo llamado currency-converter.js.

En primer lugar, requiere axios al escribir: const axios = require(‘axios’);

Nuestro objetivo es tener tres funciones para este programa. Así que, tres funciones asíncronas. La primera función es recopilar datos fetch/datos monetarios. La segunda función es obtener datos sobre los países. Y la tercera función recogerá esta información en un solo lugar y la entregará al usuario.

Primera función - Recepción asincrónica de datos de moneda

Vamos a crear una función asíncrona que va a tomar dos argumentos, desdeCurrency y toCurrency.

const getExchangeRate = async (fromCurrency, toCurrency) => {}

Ahora tenemos que recuperar los datos. Con async/await, podemos asignar datos directamente a una variable; (importante: no olvide introducir la clave de acceso.)

const getExchangeRate = async (fromCurrency, toCurrency) => {
  const response = await axios.get('http://data.fixer.io/api/latest?    access_key=[yourAccessKey]&format=1');
}

Debido a que todo se convierte a partir del euro, vamos a crear una variable llamada euro que es igual a 1/moneda de la que queremos convertir:

const euro = 1 / rate[fromCurrency];

Por último, podemos multiplicar los euros por la moneda a la que queremos convertir:

const exchangeRate = euro * rate[toCurrency];

Nuestra función debería ser así:

const getExchangeRate = async (fromCurrency, toCurrency) => {
  const response = await axios.get('http://data.fixer.io/api/latest?    access_key=[yourAccessKey]&format=1');
  const rate= response.data.rates;
  const euro = 1 / rate[fromCurrency];
  const exchangeRate = euro * rate[toCurrency];
  
  return getExchangeRate;

}

Segunda función - Recepción asincrónica de datos de país

Vamos a crear una función asíncrona que va a tomar currencyCode como argumento:

const getCountries = async (currencyCode) => {}

Como mencionamos antes, vamos a obtener datos y asignarlos a una variable:

const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);

A continuación, haremos un mapa de los datos y devolveremos el nombre del país para cada uno:

return response.data.map(country => country.name);

Aquí está nuestro último código:

const getCountries = async (currencyCode) => {
  const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);
  return response.data.map(country => country.name);
};

Tercera y última función - Fusión de todos los elementos

El siguiente paso consiste en crear una función asíncrona que va a tomar fromCurrency, toCurrency y amount como argumentos:

const convert = async (fromCurrency, toCurrency, amount) => {}

Ahora, vamos a obtener los datos de la moneda:

const exchangeRate = await getExchangeRate(fromCurrency, toCurrency);

Segundo paso, obtenemos los datos de los países:

const countries = await getCountries(toCurrency);

Además, guardamos la cantidad convertida en una variable:

const convertedAmount = (amount * exchangeRate).toFixed(2);

Finalmente, le mostraremos al usuario todo:

return `${amount} ${fromCurrency} is worth ${convertedAmount} 
${toCurrency}. You can spend these in the following countries
: ${countries}`;

Nuestro código completo:

const convert = async (fromCurrency, toCurrency, amount) => {
 const exchangeRate = await getExchangeRate(fromCurrency, toCurrency);
  const countries = await getCountries(toCurrency);
  const convertedAmount = (amount * exchangeRate).toFixed(2);
  return `${amount} ${fromCurrency} is worth ${convertedAmount} ${toCurrency}. 
  You can spend these in the following countries: ${countries}`;
};

Añadir try/catch para tratar los casos de error

Debemos usar toda nuestra lógica en el try, y atrapar (catch) el error si lo hay:

const getExchangeRate = async (fromCurrency, toCurrency) => {
  try {
    const response = await       axios.get('http://data.fixer.io/api/latest?access_key=f68b13604ac8e570a00f7d8fe7f25e1b&format=1');
    const rate = response.data.rates;
    const euro = 1 / rate[fromCurrency];
    const exchangeRate = euro * rate[toCurrency];
    return exchangeRate;
  } catch (error) {
    throw new Error(`Unable to get currency ${fromCurrency} and  ${toCurrency}`);
  }
};

Hagamos lo mismo para la segunda función:

const getCountries = async (currencyCode) => {
  try {
    const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);
return response.data.map(country => country.name);
  } catch (error) {
    throw new Error(`Unable to get countries that use ${currencyCode}`);
  }
};

Y como la tercera función sólo funciona con lo que proporcionaban la primera y la segunda, no es necesario verificar los errores. Finalmente, se puede llamar la función y recibir los datos:

convertCurrency('USD', 'HRK', 20)
  .then((message) => {
    console.log(message);
  }).catch((error) => {
    console.log(error.message);
  });

Aquí está nuestro resultado:

20 USD vale 129,90 HRK. Puede gastarlo en los siguientes países: Croacia

¡Hemos terminado!

 

 
by Janeth Kent Date: 22-02-2019 async await promises callbacks javascript tutorial visitas : 59079  
 
Janeth Kent

Janeth Kent

Licenciada en Bellas Artes y programadora por pasión. Cuando tengo un rato retoco fotos, edito vídeos y diseño cosas. El resto del tiempo escribo en MA-NO WEB DESIGN AND DEVELOPMENT.

 
 
 

Artículos relacionados

Crear PDF con Javascript y jsPDF

El formato PDF es muy útil para descargar datos de forma masiva en una aplicación web. Ayuda a los usuarios a descargar contenido dinámico en forma de archivo para que…

Como hacer tu propio cursor personalizado para tu web

Cuando empecé a ojear webs distintas y originales para aprender de ellas, de las primeras cosas que me llamaron la atención fue que algunas de ellas tenían sus propios cursores,…

Explorando la API de CSS Paint: Redondeo de formas parte 1

Añadir bordes a las formas complejas es un auténtico rollo (a veces), pero redondear las esquinas de las formas complejas es un suplicio jejeje. Por suerte, la API de pintura…

Cómo enviar un correo electrónico desde un formulario de contacto HTML

En el artículo de hoy vamos a escribir sobre cómo hacer un formulario que funcione y que al pulsar ese botón de envío sea funcional y envíe el correo electrónico…

Cómo hacer un sitio web multilingüe sin redireccionamiento

Hoy, vamos a hablar de cómo implementar un simple selector de idioma en el sitio web estático o básico, sin necesidad de ningún backend o llamadas a la base de…

Comenzando con Bootstrap-Vue paso a paso

Hoy te mostraremos cómo usar BootstrapVue, describiremos el proceso de instalación y mostraremos la funcionalidad básica. El proyecto está basado en el framework CSS más popular del mundo - Bootstrap, para…

Por qué los desarrolladores de JavaScript deberían preferir Axios a Fetch

Por qué los desarrolladores de JavaScript deberían preferir Axios a Fetch En mi artículo anterior, "Usando la Api Fetch Para Hacer Llamadas Ajax", hablé de los fundamentos de la API Fetch.…

Creación de un sencillo spinner-loader CSS

En el artículo de hoy mostraremos cómo animar un loader básico que gira cuando se define alguna acción predefinida, como cargar una imagen. Eso se puede utilizar en un sitio…

Los mejores selectores de fechas para Bootstrap y tu aplicación

Los selectores de fecha son widgets que permiten a los usuarios elegir una sola fecha o rango de fechas y horas. Es un elemento habitual para todo usuario de Internet,…

Validación de formularios HTML usando BULMA y vanilla JavaScript

Hoy vamos a escribir sobre los formularios de contacto y cómo validarlos usando JavaScript. El formulario de contacto parece ser una de las características principales de toda página web básica. Es…

Cómo usar el efecto Parallax.Js en tu sitio web

Hoy vamos a escribir sobre el efecto de parallax, similar al desplazamiento de parallax, y cómo implementarlo para mejorar su página de aterrizaje. En webdev, dicen que primero el móvil…

Usando la API FETCH para hacer llamadas AJAX - Una promesa cumplida

En este artículo hablamos sobre lo que son las llamadas AJAX y cómo utilizarlas de forma tradicional, utilizando el objeto XMLHttpRequest (XHR). En resumen, gracias a las llamadas AJAX una…

Clicky