Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Resolver problema con Async/Await

10/12
Recursos

Aportes 163

Preguntas 36

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Esta es una forma de hacer que async/await espere a varios llamados al vez:

async function foo() {
	const [characters , episodes, locations] = await Promise.all([
		getCharacters(),
		getEpisodes(),
		getLocations(),
	])

	console.log(characters)
	console.log(episodes)
	console.log(locations)
}

Mas claro echale agua. Estuve una 30min mirando la pantalla viendo porque no me funcionaba.

anotherFunction();

😦

anotherFunction(API);

😃

Me preguntaba por qué no utilizamos directamente fetch (quiza tu tambien) pues bueno, primero al estar utilizando node, no contamos con fetch, por ello hay que instalarlo.

npm i node-fetch

muestro a continuación mi ejemplo

// const fetchData = require('../utils/fetchData')
const fetch =require('node-fetch')
let API = 'https://rickandmortyapi.com/api/character/'

const anotherFunction = async (url_api) => {
    try {
        // const data = await fetchData(url_api);
        // const character = await fetchData(`${API}${data.results[0].id}`)
        // const origin = await fetchData(character.origin.url);
     
     
        const data = await (await fetch(url_api)).json();
        const character = await (await fetch(`${API}${data.results[0].id}`)).json();
        const origin = await (await fetch(character.origin.url)).json()



        console.log((data.info.count))
        console.log(character.name)
        console.log(origin.dimension)

    } catch (error) {
        console.error(error)
    }
}

console.log('Before')
anotherFunction(API)
console.log('After')

Las diferencias, como te darás cuenta tuve que usar dos await para poder obtener la data, y posterior transformarla en una respuesta .JSON, node-fetch como dependencia pesa el doble que fetchData, aunque por debajo fetch tambien hace uso del recurso XMLHttpRequest, podriamos hacer un modulo fetchData2 que nos simplifique el hacer ese doble llamado con await, pero es decision de cada quien.

Yo hice el reto desde la consola con fetch

function getData(){
return fetch("https://rickandmortyapi.com/api/character")
.then(response => response.json())
.then(json => json)
}
async function anotherFunction(){
  try{
const data = await getData()
const character = await data.results[0]
const origin = await fetch(character.origin.url)
.then(response => response.json())
.then(json => json)
console.log(data.info.count)
console.log(character.name)
console.log(origin.dimension)
}catch(error){
console.error(error)}
}

Cometió digamos un pequeño error, en:

const person = await FetchData(`${API}${data.results[0].id}`);

No era API, funciono porque la constante API era global, pero era la url que mandamos por parámetro.

Me encanto el curso!

Así lo resolví yo:

const fetchData = require('../utils/fetchData')
const API = 'https://rickandmortyapi.com/api/character/'

const getFromApi = async () => {
  const data1 = await fetchData(API)
  const { count } = data1.info
  const { id } = data1.results[0]

  const data2 = await fetchData(`${API}/${id}`)
  const { name } = data2
  const { url } = data2.origin

  const data3 = await fetchData(url)
  const { dimension } = data3

  console.log(count)
  console.log(name)
  console.log(dimension)
}
getFromApi()

Les dejo el código, con notas, espero que les ayude


// traemos nuestra funcion que llamara a la API
const fetchData = require('../utils/fechtData');
// el link de la API
const API = 'https://rickandmortyapi.com/api/character/';

// nuestra funcion asíncrona, le devemos pasar la api
const anotherFunction = async (url_api) => {
  // el TryCatch, para que se maneje de manera sincrónica
  try {
    // esperamos que se aga la primera llamada
    const data = await fetchData(url_api);

    // esperamos que se aga la segunda llamada
    const character = await fetchData(`${API}${data.results[0].id}`)

    // esperamos que se aga la tercera llamada
    const origin = await fetchData(character.origin.url);

    // imprimimos las datos de la api
    console.log(data.info.count);
    console.log(character.name);
    console.log(origin.dimension);

  } catch (error) {
    // si hay algun error lo mostramos
    console.error(error);
  }
}

console.log('before');
// mandamos a llamar nuestra api
anotherFunction(API);
console.log('After');

si eres uno de los que se pregunta que significa “TYPO” sigue leyendo :V

un TYPO es una palabra en ingles, que sigfnifica basicamente un pequeño error en la escritura de un texto.

Comparto mis apuntes 😄
⠀⠀

Resolver problema con Async/Await

⠀⠀
Ya conociendo Async/Await vamos a implementarlo en el desafío.

Creamos una función async con su estructura try()catch . Dentro de catch() pedimos que ejecuten tres peticiones. Para acceder a ellas colocamos la palabra reservada await y llamando nuestro fetchData indicamos dentro de sus parámetros la ruta que se debe tomar para acceder a la información que queremos imprimir en cada una de nuestras constantes.
⠀⠀
Después imprimimos los resultados. En catch() colocamos que código que queremos imprimir en caso de que no se cumpla la petición de try() . Ya por último llamamos la función anotherFunction() para ejecutarla.

const fetchData = require('../utils/fetchData');
const API = 'https://rickandmortyapi.com/api/character/'

const anotherFunction = async (url_api) => {
  try {
    const data = await fetchData(url_api);
    const character = await fetchData(`${url_api}${data.results[0].id}`);
    const origin = await fetchData(character.origin.url);
    console.log(data.info.count);
    console.log(character.name);
    console.log(origin.dimension);
  } catch(error) {
    console.error(error)
  }
}

console.log('Before')
anotherFunction(API)
console.log('After')

Use console.time() y console.timeEnd() para medir el tiempo de respuesta de la ejecución.

const fetchData = require('../utils/fetchData');

const API_URI = 'https://rickandmortyapi.com/api/character/';

const functionLoad = async (url_api) =>{
    console.time();
    try {
        const data = await fetchData(url_api);
        const character = await fetchData(`${url_api}${data.results[0].id}`);
        const origin = await fetchData(character.origin.url);
        const result = {count:data.info.count, name:character.name, dimension:origin.dimension}
        console.table(result);
    } catch {
        console.log(error)
    }
    console.timeEnd()
}
console.log('Inicia')
functionLoad(API_URI);
console.log('Termina')

Este fue mi resultado, usando fetch.

const fetchData = require('../utils/fetchData');
const API = "https://rickandmortyapi.com/api/character/"

const printData = async (API) => {
    const data1 = await fetchData(API);
    const data2 = await fetchData(data1.results[0].origin.url);

    const {info: {count} } = data1;
    const {name} = data1.results[0];
    const {dimension} = data2;
    console.log(count)
    console.log(name)
    console.log(dimension)
}

printData(API);

Cuando se llama a una función async, esta devuelve un elemento Promise. Cuando la función async devuelve un valor, Promise se resolverá con el valor devuelto. Si la función async genera una excepción o algún valor, Promise se rechazará con el valor generado.

Una función async puede contener una expresión await, la cual pausa la ejecución de la función asíncrona y espera la resolución de la Promise pasada y, a continuación, reanuda la ejecución de la función async y devuelve el valor resuelto.

By: https://mzl.la/2wRdFUx

Dato curioso, si intercalas las llamadas a la API con el console.log() puedes ver como poco a poco se van cumpliendo las proimesas en tu consola

	const data = await fetchData(url_api)
	console.log(data.info.count);
	const character = await fetchData(`${url_api}${data.results[0].id}`)
    console.log(character.name);
    const origin  = await fetchData(character.origin.url);
    console.log(origin.dimension);

Luego de ver 3 veces el curso, hacer el de postman, entender bien el de ecmascript y terminar el práctico de JS al fin entendí este curso

Excelente poco a poco las cosas comienzan a ser mas claras, de nuevo un experimento con otra api

const fetchData = require('../utils/fetchData');
const API = 'https://swapi.co/api/';

const fetch = async(url_api) => {
  try{
    const allData = await fetchData (url_api);
    const starship = await fetchData(`${allData.starships}${'10/'}`);
    const pilot = await fetchData(starship.pilots[0]);
    console.log(allData.starships);
    console.log(starship.name);
    console.log(pilot.name);
  }catch (error){
    console.error(error);
  }
}

fetch(API);

Profe que tema tiene usted en el VSCODE esta muy bonito.

Más que encantado

Se ve la facilidad de manejar asincronismo en cada caso viendo que disminuye el tiempo de la clase con callback, promesas y async/await, mas facil de manejar y más sencillo de explicar.
Algo que no me gusto es que haya creado el parámetro url_api para no usarlo en la constante character, si lo creo debería aprovecharlo y no pasar la API directamente.

Hola Oscar, creo que se podría refactorizar la función anotherFunction para mejorar su reutilización he independencia ya que estamos usando el valor de la constante API en la segunda llamada en vez de el valor del parametro pasado por argumento.

<javaScript>
const anotherFunction = async (url_api) => {
    try{
        const data = await FETCH_DATA(url_api)
        const character = await FETCH_DATA(`${url_api}${data.results[0].id}`)
        const origin = await FETCH_DATA(character.origin.url)

        console.log(data.info.count)
        console.log(character.name)
        console.log(origin.dimension)
    } catch (error){
        console.error(error)
    }
}
</javaScript>

challenge.js

const fetchData = require('../utils/fetch-data.js')
const API_BASE = 'https://rickandmortyapi.com/api/character/'

const anotherFunction = async (url_api) => {
    try {
        const data = await fetchData(url_api)
        const character = await fetchData(`${url_api}${data.results[0].id}`)
        const origin = await fetchData(character.origin.url)

        console.log([
            'count: ' + data.info.count, 
            'name: ' + character.name, 
            'dimension: ' + origin.dimension
        ])
    } catch (err) {
        console.error(err)
    }
}

console.log('before')
anotherFunction(API_BASE)
console.log('after')

Nota importante: Si algo se va a establecer y nunca va a cambiar, se establece, en letra mayúscula.

Para los que aun no les ha quedado claro las promesas y el async / await, este vídeo lo aclara todo de una manera muy resumida: https://www.youtube.com/watch?v=rKK1q7nFt7M

Les comparto mi versión del challenge con un condimento:

  • El momento inicial
  • el tiempo (en milisegundos) transcurrido hasta que se resolvió el 1er fetch
  • el tiempo (en milisegundos) transcurrido hasta que se resolvió el 2er fetch
  • el tiempo (en milisegundos) transcurrido hasta que se resolvió el 3er fetch

Esto ayuda también a entender que hay una secuencia de pasos, es decir hay un sincronismo determinado por los await.

const fetchData = require('../utils/fetchData');
const API = 'https://rickandmortyapi.com/api/character/';

const anotherFunction = async (url_api) => {
    try {
        var ahora = new Date();
        console.log(ahora)
        const data = await fetchData(url_api);
        var momento = new Date();
        console.info('1st fetch: ' + (momento.getTime() - ahora.getTime()) + 'ms');
        const character = await fetchData(`${url_api}${data.results[0].id}`);
        var luego = new Date();
        console.info( '2nd fetch: ' + (luego.getTime() - ahora.getTime()) + 'ms');
        const origin = await fetchData(character.origin.url);
        var despues = new Date();
        console.info( '3nd fetch: ' + (despues.getTime() - ahora.getTime()) + 'ms');
        console.log('');
        console.log('Imprimiendo respuestas:');
        console.log('=======================');
        console.log(' - Personajes: ' + data.info.count);
        console.log(' - Primer personaje: ' + character.name);
        console.log(' - Origen: ' + origin.dimension);
    } catch (err) {
        console.error(new Error(err));
    }
}

anotherFunction(API);

Hola este es el reto 😃

¿Para que pone Before y After? Si esto se ejecuta en desorden, siempre se ejecuta before y after antes.

Para los que les aparece este error:

La solucion es cambiar el require en el challenge.js por esto require(’…/…/utils/fetchData’)
ya que al ser asi: …utils/fetchData solo regresas a la carpeta anterior, la cual es src, mientras tanto, el fetchData.js esta en la carpeta utils

Mi solucion del reto quedó asi, me parece mejor guardar los datos en variables, creo que queda mas claro

const asyncFunction = async (url_1) => {
  try{
    const response1 = await fetchData(url_1);
    const { count } = response1.info;
    const { id } = response1.results[0];
    const url_2 = url_1 + id;
    console.log(count);

    const response2 = await fetchData(url_2);
    const { name } = response2;
    const url_3 = response2.origin.url;
    console.log(name);

    const response3 = await fetchData(url_3);
    const { dimension } = response3;
    console.log(dimension);

  } catch(error){
    console.error(error);
  }
}

asyncFunction(url_1);

uff al fin entendí como funciona el async await

Los primeros 20 pokemons con pokeapi 😄

const POKEAPI = "https://pokeapi.co/api/v2/";

const somePokemons = async urlApi => {
  try {
    console.log("First 20 Pokemons:");
    for (i = 0; i < 20; i++) {
      let pokemon = await fetchData(`${POKEAPI}pokemon/${i + 1}`);

      console.log(`#${pokemon.id} ${pokemon.name}`);
    }
  } catch (error) {
    console.error(error);
  }
};

somePokemons(POKEAPI);

Esta es una API que genera nombres de forma aleatoria que pueden usar en sus próximos proyectos:

https://randomuser.me/

Usando lo aprendido y haciendo unas modificaciones pueden hacer las consultas:

Primera Parte:

let XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;

const randomUserData = (url_api) => {
  return new Promise((resolve, reject) => {
    const xhttp = new XMLHttpRequest();
    xhttp.open("GET", url_api, true);
    xhttp.onreadystatechange = () => {
      if (xhttp.readyState === 4) {
        xhttp.status === 200
          ? resolve(JSON.parse(xhttp.responseText))
          : reject(new Error("Error ", url_api));
      }
    };
    xhttp.send();
  });
};

module.exports = randomUserData;

Segunda parte:

const randomUserData = require("../utils/randomUserData");

const API = "https://randomuser.me/api/";

const getUserRandom = async (url_api) => {
  try {
    const data = await randomUserData(url_api);
    //Se muestran los valores:
    //console.log(data);
    console.log("Nombre: ", data.results[0].name.first);
    console.log("Apellido: ", data.results[0].name.last);
    console.log("Ciudad: ", data.results[0].location.city);
    console.log("Correo: ", data.results[0].email);
  } catch (error) {
    console.error(error);
  }
};

console.log("Usuarios aleatorios: ");
getUserRandom(API);

10. Resolver problema con Async/Await

antes de ejecutar npm run async-await:challange, agregar los siguientes archivos y linea de código

package.json agregar script en el package.json en la sección de script

"scripts":{
"async-await:challange":  "node src/promises-with-async-await/rick-and-mortis-asyc-await",
}

folder file: src/utils/fetchData.js

// instanciamos XMLHttpRequest
const XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

const fetchData = (url_api) => {
	return new Promise((resolve, reject) => {
		const xhttp = new XMLHttpRequest();
		let reponse;
		xhttp.open('GET', url_api, true);
		xhttp.onreadystatechange = () => {
			if (xhttp.readyState === 4) {
				if (xhttp.status === 200) {
					response = JSON.parse(xhttp.responseText);
					resolve(response);
				} else {
					reponse = new Error('Error', url_api);
					reject(response);
				}
			}
		};
		xhttp.send();
	});
};

module.exports = fetchData;

folder file: src/promises-with-async-await/rick-and-mortis-asyc-await.js

const fetchData = require('../utils/fetchData');
const API = 'https://rickandmortyapi.com/api/character/';

const getInformationAPI = async function (url_api) {
	try {
		//1. Se obtienen todos los personajes
		//2. Se obtiene el primer personaje
		//3. Se obtiene la dimensión del personaje

		const data = await fetchData(url_api); //1.
		const character = await fetchData(`${API}${data.results[0].id}`); //2.
		const origin = await fetchData(character.origin.url); //3.

		console.log(data.info.count);
		console.log(character.name);
		console.log(origin.dimension);
	} catch (error) {
		console.error(error);
	}
};

Mi practica:

const fetchData = require('../utils/fetchData');
const API = "https://rickandmortyapi.com/api/character/";

const anotherFunction = async (urlApi) => {
    try {
        const data = await fetchData(urlApi);
        const character = await fetchData(`${urlApi}${data.results[0].id}`);
        const origin = await fetchData(character.origin.url);
        console.log(data.info.count);
        console.log(character.name);
        console.log(origin.dimension);
    }catch (error) {
        console.error(error)
    }
};
console.log('Before');
anotherFunction(API);
console.log('After');

Puedes trabajar importando con sintaxis ES si agregas al package.json

"type":"module"

El documento challenge.js

import { fetchData } from "../utils/fetchData.js";

const API = 'https://rickandmortyapi.com/api/character/';

const anotherFunction = async (url_api) =>{
    try {
        const data1 = await fetchData(url_api);
        console.log(data1.info.count);
        const data2 = await fetchData(`${url_api}${data1.results[0].id}`);
        console.log(data2.name);
        const data3 = await fetchData(data2.origin.url);
        console.log(data3.dimension);
    } catch (e) {
        console.error(e.message);
    }
}

anotherFunction(API);

El documento fetchData.js:

import { XMLHttpRequest } from 'xmlhttprequest';

export const fetchData = (url_api) => {
    return new Promise((resolve, reject)=>{
        const xhttp = new XMLHttpRequest();
        xhttp.open('GET',url_api,true);
            xhttp.onreadystatechange = function (event) {
            if(xhttp.readyState===4){
                if(xhttp.status === 200){
                        resolve(JSON.parse(xhttp.responseText));
                } else {
                        const error = new Error('Error '+url_api);
                        reject(error);
                }
            }
        }
        xhttp.send();
    })
}

Esta es mi implementación, explico a continuación las cosas usadas:
 


 

  1. Node fetch es un paquete de npm que nos permite usar fetch en Node JS, el cual permite hacer llamadas a api’s de manera sencilla tal como lo hariamos en el navegador .
  2. .json() el cual parsea el objecto JSON a un objeto javascript. Este devuelve una promesa por lo que hay que usar el await también.
  3. Funciones autoejecutables o IIFE( Immediately invoked function expressions) la cual como su nombre lo indica ejecuta una funcion automáticamente
     

Y es por esto que AMO async/await xD El código es más limpio, se lee mejor y todo es más hermoso ❤️

de todos los cursos el que mas me ha costado a sido el de asincronismo, quizas porque nunca lo habia visto pero ahora veo la granutilidad que tiene todo esto, gran aporte

En la línea 7 debe pasar ‘url_api’ ya que es un parámetro de la función y no directamente la constante API que fue previamente definida.

Por que en el try cuando pongo en la const origin character.origin me da error en consola???
y cuando pongo character.origin.url me da el valor correcto?

const origin = await fetchData(character.origin);
const fetchdata = require('./promide');
const API = 'https://rickandmortyapi.com/api/character/';

const fucs = async () => {
	try {
		const de = await fetchdata(API);
		console.log(de.info.count);
		const urlN = `${API}${de.results[0].id}`;
		// console.log(urlN)
		const dex = await fetchdata(urlN);
		console.log(dex.name);
		const urlNw = dex.origin.url;
		// console.log(urlNw)
		const dexy = await fetchdata(urlNw);
		console.log(dexy.dimension);
		// return await fetchdata()
	} catch (e) {
        console.log(e)
    }
};
fucs();

Lo hice antes de ver el video, y me salio muy parecido a la solucion del profe, sin duda he aprendido y me siento bastante bien por ello 😃

const fetchData = require('../utils/fetchData');
const API = 'https://rickandmortyapi.com/api/character/';

const exeFetchData = async (url_api) => {
    try {
        const response = await fetchData(url_api);
        const character = await fetchData(response.results[0].url);
        const origin = await fetchData(character.origin.url);

        const { info: { count } } = response;
        const { name } = character;
        const { dimension } = origin;

        console.log(count);
        console.log(name);
        console.log(dimension);
    } catch (error) {
        console.error(error);
    }
}

console.log('Before');
exeFetchData(API);
console.log('After');

Este es mi codigo, lo modifiquepara traerme todos los personajes
Nota: Creo que hay unos ids que no existen y por eso marca error en algunos

const fetchData = require('../utils/fetchData')
const API = 'https://rickandmortyapi.com/api/character/'

async function getCharacters(url_api){
    const data = await fetchData(url_api)
    let ids = Array.from({length:10}, (_, i) => i + 1)
    
    let promises = ids.map((id) => getCharacter(id) )
    try {
        await Promise.all(promises)
    } catch (error) {
        console.error(`${error}
        Something is missing in getCharacters`)
    }
}

async function getCharacter (id) {
    try {
        const character = await fetchData(`${API}${id}`)
        const origin = await fetchData(character.origin.url)
        
        console.log(character.name)
        console.log(origin.dimension, '\n')

    } catch (error){
        
        onError(id)
    }
}

function onError(id) {
    console.log(`It happen a error whe we try to get character ${id}`)
}

getCharacters(API)

Para mi fue mucho más sencillo entender async/await en lugar de trabajar con puras promesas o callbacks como se hizo al inicio del curso. Es excelente aprender esas formas para entender bien asincronismo en javascript

<h1>APORTE GraphQL</h1>

Les comparto mi versión del reto usando GraphQL y Async/Await.

// Dependencies
const { XMLHttpRequest } = require('xmlhttprequest');

// Settings
const API_URL = 'https://rickandmortyapi.com/graphql/';

// API
const fetchData = (query) => new Promise((resolve, reject) => {
  // Initialize request
  const xhr = new XMLHttpRequest();
  xhr.open('post', API_URL, true);
  xhr.setRequestHeader('Content-Type', 'application/json');
  
  // Response handler
  xhr.onreadystatechange = () => {
    if (xhr.readyState === 4) {
      if (xhr.status === 200) {
        return resolve(JSON.parse(xhr.responseText).data)
      }
      return reject(new Error(`${xhr.status}: Something went wrong`));
    }
  };
  
  // Error handler
  xhr.onerror = () => {
    return reject(new Error(`${xhr.status}: Something went wrong`));
  };
  
  // Send request
  xhr.send(JSON.stringify({ query }));
});

const graphQLQuery = `query {
  characters {
    info {
      count
    }
  }
  character(id: 1) {
    name
    origin {
      dimension
    }
  }
}`;


const main = async () => {
  try {
    const response = await fetchData(graphQLQuery);
    const {
      characters: { info: { count } },
      character: {
        name,
        origin: { dimension },
      },
    } = response;
  
    // Print results
    console.log(count); // -> 671
    console.log(name); // -> Rick Sanchez
    console.log(dimension); // Dimension C-137
  } catch (error) {
    throw error;
  }
};

main();

Ahora todo tiene sentido, jajajaja es mejor verlo en un caso que tal ves para muchos es más práctico y se nos hace un poco más difícil entender

Si son de explicaciones y lenguajes mas técnicos les dejo el siguiente video que complementa las clases del profesor.

Explicacion asincronismo, callbacks y promesas

En cambio si son mas de leer y leer, tomarse su tiempo y aprender pautadamente, les dejo la siguiente documentación en donde yo aprendí hace tiempo.

Promesas Mozilla dev

Este ultimo contenido es duro, que probablemente les tomara tiempo (y sufrimiento), pero luego de verlo entenderán muchas cosas que tal vez tenían en el aire o simplemente una idea.

Definitivamente todos los cursos deberían tener este tipo de explicaciones, el video anterior me dejó super confundida y ahora con este todo está super claro!

es curioso como poniendo un .then se respeta el orden del before -> anotherFunction -> after

console.log('before');
anotherFuncton(API)
    .then(() => console.log('after'))

WoW que cómodo trabajar de esta forma. Con Async & await

Con async defino una función ‘asíncrona’ y en el caso de las API guardo en memoria de manera que deben esperar a que se completen todas para poder hacer uso de ellas, esto lo hago declarándolas o asignándoles la keyword await.

Hasta que por fin pude hacerlo , solo enserio!!! dure mucho entendiendo las promesas y el async/await pero ya loe entendí completamente , Oscar explica muy bien!!!

const fetchData = require("../utils/fetchData");
const API = "https://rickandmortyapi.com/api/character/";

const anotherFunction = async (URL) => {
  try {
    const data = await fetchData(URL);
    const character = await fetchData(URL + data.results[0].id);
    return character;
  } catch (error) {
    console.error(error);
  }
};

anotherFunction(API)
  .then((res) =>
    console.table([
      { Name: res.name },
      { Planet: res.origin.name },
      { Species: res.species },
    ])
  )
  .catch((err) => console.log(err));

┌─────────┬────────────────┬─────────────────┬─────────┐
│ (index) │      Name      │     Planet      │ Species │
├─────────┼────────────────┼─────────────────┼─────────┤
│    0'Rick Sanchez' │                 │         │
│    1    │                │ 'Earth (C-137)' │         │
│    2    │                │                 │ 'Human' │
└─────────┴────────────────┴─────────────────┴─────────┘

Con async defino una función ‘asíncrona’ y en el caso de las API guardo en memoria de manera que deben esperar a que se completen todas para poder hacer uso de ellas, esto lo hago declarándolas o asignándoles la keyword await. Feedback please!

const fetchData = require('../utils/fetchData');
let API = 'https://rickandmortyapi.com/api/character/';

const anotherFuncton = async (url_api) =>{
    try{
        const data = await fetchData(url_api);
        const character = await fetchData(`${url_api}${data.results[0].id}`);
        const origin = await fetchData(`${character.origin.url}`);
        
        console.log(data.info.count);
        console.log(character.name);
        console.log(origin.dimension);
    }catch(e){
        console.log(e);
    }
};

console.log('before');
anotherFuncton(API);
console.log('after')
const fetchData = require('../utils/fetchData')
const API = 'https://rickandmortyapi.com/api/character/'

const anotherFunction = async (url_api) => {
  try{
    const data = await fetchData(url_api)
    const character = await fetchData(`${API}${data.results[0].id}`)
    const origin =await fetchData(character.origin.url)

    console.log(data.info.count)
    console.log(character.name)
    console.log(origin.dimension)
  }catch(error){
    console.error(error)
  }
}

console.log('Before')
anotherFunction(API)
console.log('After')
const { fetchData } = require('../utils/fetchData');
const API = 'https://rickandmortyapi.com/api/character/'

const anotherFunction = async (url_api) => {
    try {
        const { results, info: { count } } = await fetchData(url_api);
        const { origin: { url }, name } = await fetchData(`${url_api}${results[0].id}`)
        const { dimension } = await fetchData(url)

        console.log(`
            Cantidad de personajes: ${count}
            Personaje: ${name}
            Dimension: ${dimension}
        `)
    } catch (error) {
        console.error(error);
    }
};

anotherFunction(API)```

Requests a API’s con async/await

Llegamos a la última forma de hacer peticiones, con una implementación de ECMAScript 8, async y await. Este método es mucho más fácil de leer y comprender.

Objetivos

De la API queremos:

  1. Conocer el número de personajes que hay.
  2. El nombre del primer personaje.
  3. La dimensión del primer personaje.

Importando una vieja función

Importaremos la función fetchData que creamos con las promesas, para usarla en este proyecto. Lo haremos de la siguiente forma:

const fetchData = require('./directory/');

La API en una constante:

const API = '[https://rickandmortyapi.com/api/character/](https://rickandmortyapi.com/api/character/)';

Crearemos una arrow function con async:

const anotherFunction = async (url_api) => {
	
}

Usaremos try y catch con una estructura similar a if y else:

const anotherFunction = async (url_api) => {
	try {
  } catch {
  }
}

Atraparemos un error en caso de que haya uno:

const anotherFunction = async (url_api) => {
	try {

  } catch (error) {
	  console.error(error);
  }
}

Haremos la primera petición. En la variable data ya tenemos información en JSON y podemos acceder al número de personajes, así que imprimiremos nuestro primer objetivo:

const anotherFunction = async (url_api) => {
	try {
	  const data = await fetchData(url_api);
    console.log(data.info.count);
  } catch (error) {
	  console.error(error);
  }
}

Haremos una segunda petición, entrando al primer personaje, con la variable character ya tenemos el JSON del primer personaje, entonces nos queda imprimir su nombre.

const anotherFunction = async (url_api) => {
	try {
	  const data = await fetchData(url_api);
    console.log(data.info.count);
    const character = await fetchData(`${url_api}${data.results[0].id}`);
    console.log(character.name);
  } catch (error) {
	  console.error(error);
  }
}

Ahora, haremos la última petición, entrando a una nueva sección de la API, conseguimos el URL del JSON en character, finalmente imprimimos nuestra dimension.

const anotherFunction = async (url_api) => {
	try {
	  const data = await fetchData(url_api);
    console.log(data.info.count);
    const character = await fetchData(`${url_api}${data.results[0].id}`);
    console.log(character.name);
    const origin = await fetchData(character.origin.url);
    console.log(origin.dimension);
  } catch (error) {
	  console.error(error);
  }
}

Ya casi cumplimos nuestros objetivos, ahora debemos utilizar la función:

anotherFunction(API);

¡Saludos platzinauta, nunca pares de aprender! 🙋🏿‍♂️🖤

Me parece que esta metodologia de async y await aporta mas beneficios a nuestro codigo y genera mejor visibilidad y rendimiento.

A alguien mas le pasa que da error cuando se llama data.results[1].id?? no tengo problema con los otros personajes pero Morty esta maldito :c ¿Como es que hasta Jerry sale en el id 5? ¿es esto cosa del evil Morty? (prueben dando console.log(data))

let XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
let API = 'https://rickandmortyapi.com/api/character/'


function fetchData(url_api, callback){
    let xhttp = new XMLHttpRequest();

    xhttp.open('GET', url_api, true);
    xhttp.onreadystatechange = function(event){
        if(xhttp.readyState === 4 ){
            if(xhttp.status === 200){
                callback(null, JSON.parse(xhttp.responseText));
            }else{
                const error = new Error('error' + url_api);
                return callback(error, null);
            }
        }
    }
    xhttp.send();
}

fetchData(API, function(error1, data1){
    if(error1) return console.error(error1);
    fetchData(API+data1, function(error2, data2){
        if(error2) return console.error(error2);
        fetchData(data2.origin.url, function(error3, data3){
            if(error3) return console.error(error3);
            console.log(data1.info.count);
            console.log(data2.name);
            console.log(data3.dimension);
        })
    })
})

Yo intente abordarlo primera con lo que me habia quedado y este fue el resultado antes de ver la clase.


const resultado = async () => {
    try {
    const data = await fetchData(API);
    console.log(data.info.count);
    const data2 = await fetchData(`${API}${data.results[0].id}`);
    console.log(data2.name);
    const data3 = await fetchData(data2.origin.url);
    console.log(data3.dimension);
    } catch(error) {
        console.error(error);
    }
}

resultado();

Ame esta sintaxis, antes estaba tratando de traer mas datos de la api y no lo tenia claro. Ahora que lo intente con esta lo logre

Estuvo bien la clase. Pero hubiera sido perfecta si se empleara el método fetch para hacer el llamado a la API.

Interesante como con cada método la clase se va haciendo más corta, al igual que el código

saben si hay un curso para saber como manejar json? me cuesta mucho el tema de concatenar por ejemplo:
${API}${data.results[0].id}

Este tema me ha costado pero acá tengo otra aproximación del ejercicio. Quise obtener algunas características del personaje consultado y además los nombres de los episodios en los que aparece. Acá está el resultado:

const fetchData = require("./fetchData");
const URI = 'https://rickandmortyapi.com/api/character/';


const getCharacterById = async (id) => {
  const character = await fetchData(URI+id);
  return character;
}

const getEpisodesName = (episodes_url) => Promise.all( episodes_url.map(episode => fetchData(episode)) );

const printResponses = async () => {
  const character = await getCharacterById(5);
  const {name,species,status,episode} = character;
  const episodesList = await getEpisodesName(episode);
  console.log({name,species,status});
  episodesList.forEach( episode => console.log(episode.name,episode.episode) )
}

La función fetchData() la hice con el módulo https, que es nativo de node.

const https = require("https");

const fetchData = (URI) => new Promise( (resolve,reject)=> {
  https.get(URI, res => {
    res.setEncoding('utf-8');
    let body = '';
    if (res.statusCode!==200) {
      reject(new Error(`Error: status ${res.statusCode}`));
    }
    res.on('data', dat => body += dat);
    res.on('end', () => {
      const response = JSON.parse(body);
      resolve(response);
    })
  })
})

module.exports = fetchData;

Creo que tengo una acotación, y es que en la linea 7, debió colocar ‘url_api’ en vez de colocar de una el API ya que estaba declarando.

Definitivamente es más cómodo y practico con Async/Await pero debo reforzar mucho más los conocimientos. Quizás repetir el curso, pues para mí está siendo algo complejo. No por ello deja de ser una excelente clase

const fetchData=require('../utils/fetchData');
const API = "https://rickandmortyapi.com/api/character/";

const anotherFunction=async(url_api)=>{
    try {
        const data=await fetchData(url_api);
        const character=await fetchData(`${url_api}${data?.results[0]?.id}`);
        const origin=await fetchData(character.origin.url);

        console.log(data?.info?.count)
        console.log(character?.name);
        console.log(origin?.dimension)
    } catch (error) {
        console.error(error)
    }
}

anotherFunction(API);

Necesito ayuda con este error. No lo encuentro en ningún lado y mi código es exactamente igual al del profe.

const fetchData = require("../utils/fetchdata");
const API = "https://rickandmortyapi.com/api/character/";

const anotherFunction = async (url_api) => {
  try {
    const data = await fetchData(url_api);
    const character = await fetchData(`${API}${data.results[0].id}`);
    const origin = await fetchData(character.origin.url);
    console.log(data.info.count);
    console.log(character.name);
    console.log(origin.dimension);
  } catch (error) {
    console.error(error);
  }
};

console.log("before");
anotherFunction();
console.log("after");

Fetch Data

let XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;

const fetchData = (url_api) => {
  return new Promise((resolve, reject) => {
    const xhttp = new XMLHttpRequest();
    xhttp.open("GET", url_api, true);
    xhttp.onreadystatechange = () => {
      if (xhttp.readyState === 4) {
        xhttp.status === 200
          ? resolve(JSON.parse(xhttp.responseText))
          : reject(new Error("Error ", url_api));
      }
    };
    xhttp.send();
  });
};

module.exports = fetchData;

Error de la consola

$ npm run async:challenge

> [email protected] async:challenge
> node src/async/challenge.js

before
after
TypeError: Cannot read property 'toString' of undefined
    at exports.XMLHttpRequest.open (D:\eduar\OneDrive\Estudio\Platzi\Cursos\Desarrollo Web\Agosto 2021 - Curso de Asincronismo 
con JavaScript\node_modules\xmlhttprequest\lib\XMLHttpRequest.js:167:18)
    at D:\eduar\OneDrive\Estudio\Platzi\Cursos\Desarrollo Web\Agosto 2021 - Curso de Asincronismo con JavaScript\src\utils\fetchdata.js:6:11
    at new Promise (<anonymous>)
    at fetchData (D:\eduar\OneDrive\Estudio\Platzi\Cursos\Desarrollo Web\Agosto 2021 - Curso de Asincronismo con JavaScript\src\utils\fetchdata.js:4:10)
    at anotherFunction (D:\eduar\OneDrive\Estudio\Platzi\Cursos\Desarrollo Web\Agosto 2021 - Curso de Asincronismo con JavaScript\src\async\challenge.js:6:24)
    at Object.<anonymous> (D:\eduar\OneDrive\Estudio\Platzi\Cursos\Desarrollo Web\Agosto 2021 - Curso de Asincronismo con JavaScript\src\async\challenge.js:19:1)
    at Module._compile (node:internal/modules/cjs/loader:1102:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1131:10)
    at Module.load (node:internal/modules/cjs/loader:967:32)
    at Function.Module._load (node:internal/modules/cjs/loader:807:14)

En ECMAScript 10 se implementó una funcionalidad llamada Optional catch binding y es que normalmente cuando utilizábamos el try catch nos veíamos obligados a pasarle como parámetro el error al catch. Algo como catch(error) pues ahora eso es opcional y podemos poner simplemente catch

//Primero se trae la function fetchData que es la que conecta nuestro programa con la API de Rick and Morty


const fetchData = require("../utils/fetchData");
//API en mayuscula es una convencion para las variables qcuyo valor nunca cambian
const API = "https://rickandmortyapi.com/api/character/";

const anotherFunction = async (url_api) => {
    try {

        //Los datos de la api se muestran todos completos y no uno por uno por que await espera a que sus funciones esten todas ejecutas y despues si muestra sus resultados
        const data = await fetchData(url_api)
        const character = await fetchData(`${API}${data.results[4].id}`)
        const origin = await fetchData(character.origin.url)
        
        console.log(data.info.count);
        console.log(character.name);
        console.log(origin.dimension);
    } catch (error) {
        console.error(error);
    }
}

console.log("Before");
anotherFunction(API);
console.log("After");

Todos somos valiosos :3

Compañeros mejoren su console.log() y pongan en practica lo aprendido.

    const data = await fetchData(url_api);
    const personajeCount = data.info.count;

    const character = await fetchData(`${API}${data.results[0].id}`);
    const rickName = character.name;

    const origin = await fetchData(character.origin.url);
    const rickDimension = origin.dimension;

    console.log(
      {personajeCount,
      rickName,
      rickDimension,
    });

Edité un poco el código para que fuera más didáctico:

//importamos fetchData
const fetchData = require('../utils/fetchData')
const API = 'https://rickandmortyapi.com/api/character/';

const anotherFunction = async (url_api) => {
    try{
        const data = await fetchData(url_api);
        console.log('Llamamos data')
        console.log(data.info.count);

        const character = await fetchData(`${url_api}${data.results[0].id}`);
        console.log('Llamamos character')
        console.log(character.name);

        const origin = await fetchData(character.origin.url);
        console.log('Llamamos origin')
        console.log(origin.dimension);

    }catch(error){
        console.log(error);
    }
};

console.log('Before');
anotherFunction(API);
console.log('After');

Salida:

Before
After
Llamamos data
671
Llamamos character
Rick Sanchez
Llamamos origin
Dimension C-137

Conclusión: Await sólo espera dentro de la async function, mas no bloquea el código fuera de esta.

Hice una modificación al código y ahora puedes buscarlo por nombre 😄

Les dejo el código por si quieren probarlo

const fetch = require("node-fetch");
let API = "https://rickandmortyapi.com/api/character/?name=";

const dataExt = async (api_url, name) => {
  try {
    const character = await fetch(`${api_url}${name}`).then((res) =>
      res.json()
    );
    if (!character.error) {
      const char = character.results[0];
      const origin = await fetch(`${char.origin.url}`)
        .then((res) => res.json())
        .catch(function () {
          return {
            dimension: "none",
          };
        });
      console.log(`Name: ${char.name}`);
      console.log(`Status: ${char.status} - ${char.species}`);
      console.log(`Dimension: ${origin.dimension}`);
    } else {
      console.log("Personaje no encontrado");
    }
  } catch (error) {
    console.error(error);
  }
};

dataExt(API, "christmas");

Utilizando la API fetch:

const API = 'https://rickandmortyapi.com/api/character/';

function fetchData(API) {
    return new Promise((res,rej) => {
    fetch(API)
        .then( response => response.json() )
        .then( data => res(data) )
        .catch( e => rej(e,API) )
    })
}


async function getData() {
    try{
        const data = await fetchData(API);
        const character = await fetchData(`${API}${data.results[0].id}`)
        const dimension = await fetchData(character.origin.url);

        console.log(data.info.count);
        console.log(character.name);
        console.log(dimension.dimension);
    }catch(er) {
        console.error('Error', er);
    }
}

getData();

El código es mucho más legible de esa forma.

const fetchData = require('../utils/fetchData');
const API = 'https://rickandmortyapi.com/api/character/' //Se asigna en mayúscula un valor que sabemos que no va a variar, como el URL de la api.

const anotherFunction = async (url_api) => {
    try {
        const data = await fetchData(url_api); //Se indica que espere hasta que la petición se cumpla y ya cuento con data cargada.
        const character = await fetchData(`${API}${data.results[0].id}`);
        const origin = await fetchData(character.origin.url);
        console.log(data.info.count);
        console.log(character.name);
        console.log(origin.dimension);
    } catch (error) {
        console.log(error);
    }
}

console.log('Before');
anotherFunction(API);
console.log('After');

llegar hasta aquí y pensar que este era un tema duro pero ya lo veo mejor jjj

Hermoso!, felicitaciones por el curso concreto pero muy entendible el async await!

//importamos fetchData
const fetchData = require('../utils/fetchData')
//url de la api
const API = 'https://rickandmortyapi.com/api/character/'

//creamos la funcion
const anotherFunction = async (url_api) => {
    //iniciamos try catch
    try {
        //realizamos las 3 consultas
        const data = await fetchData(url_api)
        const character = await fetchData(`${API}${data.results[0].id}`)
        const origin = await fetchData(character.origin.url)

        //imprimimos los resultados
        console.log(data.info.count);
        console.log(character.name);
        console.log(origin.dimension);
    
    //en caso de error    
    } catch (error) {
        console.error(error);
    }
}

//imprimimos "Before", "After" y ejecutamos la funcion
console.log('Before');
anotherFunction(API)
console.log('After');

Ejecutando nuestro código en la terminal

Añadiendo nuestro script en package.json

Implementando una función para trabajar con async/await

Agregando la función fetchData

Preparando nuestro proyecto

Súper buena esta clase, sin duda con el async y await se ve mucho mejor.

GRAAN CURSO

Excelente práctica.

const fetchData = require('../utils/fetchData');
const API = 'https://rickandmortyapi.com/api/character/';

const anotherFunction = async (url_api) => {
    try{
        const data = await fetchData(url_api);
        const character = await fetchData(`${API}${data.results[0].id}`);
        const origin = await fetchData(character.origin.url);
        console.log(data.info.count);
        console.log(character.name);
        console.log(origin.dimension);
    }
    catch (error){
        console.log(error);
    }
}

console.log('Before');
anotherFunction(API);
console.log('After');

Me parece genial como el async/await complementan las promesas y hacen un código mucho más sencillo y entendible al momento de desarrollar!

const fetchData = require('../Utils/fetchData')
const API =  'https://rickandmortyapi.com/api/character/'

const anotherFunction = async (url_api) => {
    try {
        const data  = await fetchData(url_api)
        const character = await fetchData(`${API}${data.results[10].id}`)
        const origin = await fetchData(character.origin.url)
        console.log(data.info.count)
        console.log(character.name)
        console.log(origin.dimension)
    } catch (error) {
        console.error(error)
    }
}

console.log('Before DBZ Challenge')
anotherFunction(API)
console.log('After DBZ Challenge')

La verdad que muy buenos ejemplos y la manera de explicar es excelente!

Donde se encuentran esas convenciones de las que habla el profesor? De la utilización de ; y de las constantes en mayúsculas.

Con async/await el codigo se hace menos largo y mas entendible, bastante util estos metodos. Gracias profesor, muy buena explicacion en este tema.

const fetchData = require('../utils/fetchData');
const API = 'https://rickandmortyapi.com/api/character/';

const anotherFunction = async(url_api) => {
    try {
        const data = await fetchData(url_api);
        const character = await fetchData(`${url_api}${data.results[0].id}`);
        const origin = await fetchData(character.origin.url);

        console.log(data.info.count);
        console.log(character.name);
        console.log(origin.dimension);

    } catch (error) {
        console.error(error);
    }
}


console.log('Before')
anotherFunction(API);
console.log('After');```

Pense que async/await harían el código sincrono. Por lo que las salidas en pantalla serian
Before
[Info de Rick Sanchez]
Await
Por que esto no es así?

Muy buenos ejemplos. Gracias.