No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Convierte tus certificados en títulos universitarios en USA

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

19 Días
9 Hrs
50 Min
31 Seg

Try and catch

16/26
Recursos

Aportes 55

Preguntas 20

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

🎭 𝗖𝗹𝗮𝘀𝗲 #𝟭𝟰: 𝗧𝗿𝘆 𝗮𝗻𝗱 𝗰𝗮𝘁𝗰𝗵 𝟭𝟰/𝟮𝟭 🎭
.
En ésta clase vamos a implementar lo aprendido de async/await usando la API y una nueva estructura con try/catch.
.
🚨 Importante recordar que la estructura de async/await se compone por las palabras reservadas async y await:
.

  1. La palabra async se coloca antes de la función (la otra forma es con funciones flecha en que el async va antes que los argumentos).
  2. La palabra await se utiliza dentro de las funciones async.
    .

🖇️ Otra forma de hacer que async/await espere a varios llamados a la vez es con la estructura: Try /Catch:
.

  • La palabra reservada try consiste en un bloque que contiene una o más sentencias, como hacíamos con resolve.
    • Su cuerpo está conformado por las llaves {} las cuales se deben utilizar siempre, incluso para un bloque de una sola sentencia.
  • También puede estar presente un bloque con la palabra reservada catch.
    • Un bloque catch es opcional (como hacíamos con reject) y contiene sentencias que especifican que hacer si una excepción es lanzada en el bloque try.
    • Si no se lanza ninguna excepción en el bloque try, el bloque catch se omite.
      .

✏️ Ejemplo:
La estructura try / catch se asemeja a if / else, solo que catch puede detectar un error en caso de que haya uno:

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

        } catch (error){

        }
}

.
🛠️ - Siguiendo con el proyecto, ir a VSC, crear en src/async el archivo challenge.js

  • El código (comentado) de src/ async/challenge.js queda:
import fetch from 'node-fetch';
const API = 'https://api.escuelajs.co/api/v1';

//Lógica de async: ir por los datos, luego esperar por ellos y finalmente retornarlos hacia el usuario
async function fetchData(urlApi) { //siempre async antes de function
    const response = await fetch(urlApi); //hacemos uso del fetch()
    const data = await response.json(); //estructura de los datos transformandolos en json
    return data; //retorna la información de la API que estamos solicitando
}

//también se puede colocar la palabra async antes del argumento y se usa arrow function
const anotherFunction = async (urlApi) => {
    //En try estará todo lo que queremos que suceda con la lógica de la aplicación
    try{
        const products = await fetchData(`${urlApi}/products`);
        const product = await fetchData(`${urlApi}/products/${products[0].id}`);
        const category = await fetchData(`${urlApi}/categories/${product.category.id}`);

        console.log(products);
        console.log(product.title);
        console.log(category.name);
    } catch(error) { //Atraparemos un error en caso de que haya uno
        console.error(error);
    }
}

anotherFunction(API); //se hace el llamado

🖥️ Salida de src/async/challenge.js
.

  • Cuando se ejecuta console.log(products); en fetchData se solicita todos los productos de la API con ${urlApi}/products es por eso que vemos en la salida una larga lista de bloques entre corchetes [] y separados por llaves {}.
    .
  • Cuando se ejecuta console.log(product.title); en fetchData se solicita el título de un producto en particular accediendo al atributo title, para ello tenemos que con ${urlApi}/products/${products[0].id} el cero 0 indica la posición de products que acabamos de almacenar la lista de productos, pero debe finalizar con id porque esa es la forma para acceder al objeto con ese identificador en la posición cero.
    • Si solo colocamos ${urlApi}/products/${products[0]} sin el .id, en la consola tendríamos un error de tipo: TypeError: Cannot read properties of undefined (reading 'id') así que no podemos acceder.
      .
  • Cuando se ejecuta console.log(category.name); en fetchData se solicita el nombre de la categoría que corresponda al producto que se llamó anteriormente, para ello tenemos ${urlApi}/categories/${product.category.id} y no es necesario indicar la posición porque por cada producto, solo hay un bloque de categoría.

Resumen de la clase paso a paso…

Para los nuevos o los que se les hizo confuso entender la lógica aquí un resumen.
Primero y principal, para entender lo que estamos haciendo es importante saber que queremos hacer; En este caso consumir la API y traer todos los productos, filtrar el nombre de un producto y categoría a la que pertenece, además debemos ir revisando la documentación de la API, esto nos permitirá comprender mejor los llamados que hacemos.
.

Primera parte

Lo primero que hacemos es crear una función “principal” para consumir la API. Recordemos que la constante API, es la url base, es decir si queremos ver que nos devuelve data, nos marcará un error por que la url esta incompleta, ya que si revisan la doc, se necesita mínimo un endpoint (products, categories, user, etc) para devolvernos algo, este endpoint será colocado posteriormente

import fetch from 'node-fetch';
const API = 'https://api.escuelajs.co/api/v1'; //link principal de la API

async function fetchData(urlApi){
    const response = await fetch (urlApi); //consumimos la API, nos devuelve en un formato que no podemos trabajar en JS
    const data = await response.json() //convertimos en formato json (objetos y arrays) para manipularlo     
    return(data);
}

.

Segunda Parte

Creamos la función asíncrona guardada en la variable “anotherFunction” donde iremos haciendo cada uno de los llamados.
Lo primero que hacemos es traernos todos los productos que contiene la API, que si revisamos la documentación nos dice que necesitamos esta URL

https://api.escuelajs.co/api/v1/products

Por ello en la variable “products” ejecutamos la funcion “principal” en este caso “fetchData”, le colocamos la url base almacenada en “urlApi” pero aqui ya le estamos agregando el endpoint que mencioné anteriormente, en este caso /products, y con esto en esta variable ya tenemos el array con todos los productos.
En el siguiente llamado en la variable “product” necesitamos traer el objeto de un solo producto, en la doc nos dice que es el mismo link, pero agregado el id del # del producto que queramos, en nuestro caso estamos “desglosando” del array principal con todos los productos (products), el primer producto en la posición 0 y nos traemos el id de ese producto, y en esta variable(product) ya tenemos el objeto de un producto en especifico.

const anotherFunction = async (urlApi) => {
    try{
        const products = await fetchData(`${urlApi}/products`)  //consumimos la api con todos los productos 
        const product = await fetchData (`${urlApi}/products/${products[0].id}`) //traemos el objeto de un solo prodcuto (revisar doc para la api)
        const category = await fetchData (`${urlApi}/categories/${product.category.id}`) //traemos el obj category, dentro del obj producto por el id
        
        console.log(products) 
        console.log(product.title)
        console.log(category.name)
    } catch (error){
        console.error(error)
    }
} 

anotherFunction(API)

Luego necesitamos saber la categoría de este producto, en donde el link según la doc es esta.
El 1 representa el id que corresponde a la categoría del producto(diferente al id del producto como tal), ahora recordemos que la categoría(llamado category) es un objeto que está dentro del objeto del producto, entonces en el llamado colocamos la url base, el endpoint categories, y luego el id de la categoría (“desglosado” como se muestra)

https://api.escuelajs.co/api/v1/categories/1 

Y ya para concluir mostramos en los console.log lo que necesitamos es decir el array con todos los productos, el nombre del producto, y la categoría a la que corresponde. Ejecutamos la función antoherFunction pasándole el valor del parámetro API, que será reemplazado por urlApi y ya estamos.
.
Espero que le sirva de algo sobre todo para los que somos nuevos entendiendo éstos temas, mas adelante en los cursos de consumo de API REST fortalecerán estos conceptos. Y cualquier duda o aclaración háganla saber 😃

TRY AND CATCH
Nos permite crear un bloque para lo que seria el “resolve” con try. Y otro bloque para lo que seria el “reject” con catch. los pasos son los siguientes:
Hacemos el importe de fetch y llamamos la API

import fetch from "node-fetch";
const API = 'https://api.escuelajs.co/api/v1

creamos la funcion de fetchData la cual utiliza la APi y retornamos la informacion en un tipo objeto JSON, implementando la logica de async y await, en este ejemplo usamos una funcion tradicional

async function fetchData(urlApi) {
    //traemos la informacion de la API con la funcion response
    const response = await fetch(urlApi);
    //transformamos la informacion a un objeto json
    const data = await response.json();
    //retornamos el objeto json
    return data;
}

creamos la funcion que realiza las solicitudes en la que utilizamos try y catch. En esta ocasion usamos una funcion arrow (nueva)

const anotherFn = async (urlApi) => {
    try {
        //segun nuestro ejercicio debemmos llamar primero todos los productos
        const products = await fetchData(`${urlApi}/products`);
        //en el ejercicio, dice que llamamos el primer producto del array que generamos en el paso anterior con su id
        const product = await fetchData(`${urlApi}/products/${products[0].id}`);
        //segun el ejercicio debemos llamar la categoia del producto anterior
        const category = await fetchData(`${urlApi}/categories/${product.category.id}`);

        //imprimimos los resultados en el mismo orden de los llamados de la funcion anterior
        console.log(products);
        console.log(product.title);
        console.log(category.name);
        //si hay errores, los capturamos con catch en su console.error
    } catch (error) {
        console.error(error);
    }
}
//llamamos nuestra funcion dandole como argumento la API la cual va a prepararse segun sean los llamados en la funcion anterior
anotherFn(API);

Cabe anotar que fetch en si misma maneja las promesas

en mi cabeza hice una analogia para entender esto en particular (jeje tal vez no me entiendan), pero a la funcion ‘fetchData’ lo puse como una persona que estaba por alla en una bodega de zapatos (o caulquier cosa) donde tenia toda la info de los productos, y la funcion anotherFuncion como un vendedor, entonces cuando venia un cliente que quiere saber cuantas ref de zapatos tienen, categorias etc… (hagase referencia a las variables que estan dentro del TRY) se comunicaban entre ellos (simulando el await) y al finalizar daba una respuesta al cliente 😄

Async y Await son mucho más legibles y cómodos de usar 💚

Me esta encantando este curos

A mi me ayuda mucho ver la clase, hacerlo por mi cuenta y comentar todo el proceso para ir entendiendo lo que estoy haciendo

import fetch from "node-fetch";
const API = "https://api.escuelajs.co/api/v1";

//aqui hacemos una funcion normal con async(solo pq si) pero tambien puede ser como la de abajo
//solo se hizo con fines educativos, puedes elegir la manera que te guste mas
async function fecthData(urlApi) {
  const response = await fetch(urlApi); //fecth se refiere a una promesa
  const data = response.json(); //debemos transformar la llamada en json para poder usar esos datos
  return data; // los devolvemos ya transformados
}

//ahora procedemos a consumir la api para obtener todos los productos

const consumirApi = async (urlApi) => {
  try {
    //accedemos a todos los productos usando await para que el codigo "espere" dicha solicitud
    const products = await fecthData(`${API}/products`);
    //ya que tenemos los productos, buscamos el primero con products[0] siendo esta la constante en la linea anterior junto con su id
    const product = await fecthData(`${API}/products/${products[0].id}`);
    //ahora ya tengo el producto, quiero filtrarlo por categoria y para ello uso el id
    const category = await fecthData(
      `${API}/categories/${product.category.id}`
    );
    //ahora simplemente mostramos en consola los resultados obtenidos
    console.log(products);
    //en este llamado podemos acceder al nombre del producto que esta por "title"
    console.log(product.title);
    //en este llamado accedemos al nombre de la categoria que esta por "name"
    console.log(category.name);
    //todo esto se sabe por la documentacion de la API de platzi
  } catch (error) {
    console.error(error);
  }
  //el try y catch es digamos un "intenta esto" y sino "lanza el error(catch)"
};

//ahora solo queda llamar a la funcion pasandole la API de platzi

consumirApi(API);

Espero les sirva 😃

No entiendes para que usar la estructura TRY y CATCH?
.
Bien, esta explicacion te servirá, es muy simple.
.
Imagina que no usas la estructura try y catch en la segunda funcion, donde recibes la respuesta de la peticion. Bueno, lo que va a pasar es que si hay un error en esa petición por un error tuyo al hacer la logica o un error de sintaxis, la ejecución se va a detener por completo y todo se caerá. ya sabes que js tumba todo el codigo si hay un error.
.
Eso no sería nada agradable para el usuario, porque esos errores pueden a veces pasar o a veces no.
.
La estructura try y catch es en caso de que se generen esos errores. Si hay un error, entonces la información de ese error se va al parametro de catch y luego tu puedes usar ese parametro para ver el error PERO sin que toda la app se caiga. Con esa estructura, js mandará el error al catch pero seguirá con la ejecución de la app normalmente

Una adaptación de lo que realizo el profe Oscar con la API de Rick and Morty. Con 2 funciones para traer todos los personajes o 1 en específico

import fetch from "node-fetch";
const API = 'https://rickandmortyapi.com/api';

async function fetchData(urlApi) {
    const response = await fetch(urlApi);
    const data = await response.json();
    return data;
}

const allCharac = async (urlApi) => {
    try {
        const character = await fetchData(`${urlApi}/character`);
        console.log(character);
    } catch (e) {
        console.error(e);
    }
}

const oneCharac = async (urlApi, num) => {
    try {
        const Ocharacter = await fetchData(`${urlApi}/character/${num}`);
        console.log(Ocharacter);
    } catch (e) {
        console.error(e);
    }
}

//allCharac(API);
oneCharac(API,2);

solo sé que odio los callbacks hell

🔥 KISS 🎸

El principio KISS (Keep It Simple, Stupid): mantenlo simple, estúpido, es uno de los principios de programación más conocidos y se refiere al código fuente de un programa que debe ser simple y directo desde el principio.

✨🤗 Lo mismo pero más barato

import fetch from 'node-fetch';
const API = 'https://api.escuelajs.co/api/v1'

const fetchFunction = async () => {
	try {
		const response = await fetch(`${API}/products`);
		const data = await response.json();
		console.log({
			//data: data[0],
			title: data[0].title,
			category: data[0].category.name,
		});
	} catch (err) {
		console.error(err);
	}
}

fetchFunction();
* *try es como decir "prueba esto".* * *catch es como decir "si algo sale mal, haz esto en su lugar".* Con async/await, try...catch ayuda a manejar errores de manera más legible y estructurada, permitiendo un control más fácil sobre situaciones inesperadas que puedan surgir en el código asíncrono.

16/26 Curso de Asincronismo: Try & catch

El uso de try y catch en JavaScript es una técnica fundamental para manejar errores y excepciones en tu código. Aquí tienes un ejemplo básico de cómo funciona:

try {
  // Código que puede generar un error
  // Por ejemplo, intentemos dividir por cero
  let resultado = 10 / 0;
  console.log(resultado); // Esto nunca se ejecutará debido al error
} catch (error) {
  // Este bloque se ejecutará si se produce un error
  console.error("Se produjo un error: " + error.message);
} finally {
  // Este bloque se ejecutará siempre, con o sin error
  console.log("Finalizado el proceso");
}


En el código anterior, intentamos dividir 10 por 0, lo que generará un error de división por cero. El bloque try se utiliza para envolver el código que puede generar un error. Si ocurre un error dentro del bloque try, el flujo de control se transfiere al bloque catch, donde puedes manejar el error. En este ejemplo, simplemente imprimimos un mensaje de error que muestra el mensaje de error generado por JavaScript.

El bloque finally es opcional y se ejecuta siempre, independientemente de si se produjo un error o no. Es útil para realizar tareas de limpieza o liberación de recursos.

Puedes personalizar el manejo de errores en el bloque catch para tomar medidas específicas según el tipo de error o para registrar información detallada sobre el error.


Veamos el código de la clase paso a paso:

import fetch from "node-fetch";
const API = "https://api.escuelajs.co/api/v1";

async function fetchData(urlApi) {
  const response = await fetch(urlApi);
  const data = await response.json();
  return data;
}

const anotherFunction = async (urlApi) => {
  try {
    const products = await fetchData(`${urlApi}/products`);
    const product = await fetchData(`${urlApi}/products/${products[0].id}`);
    const category = await fetchData(
      `${urlApi}/categories/${product.category.id}`
    );

    console.log(products);
    console.log(product.title);
    console.log(category.name);
  } catch (error) {
    console.error(error);
  }
};

anotherFunction(API);

  1. Importación de módulos: En primer lugar, el código importa el módulo fetch de la biblioteca node-fetch. Esto se utiliza para realizar solicitudes HTTP en Node.js. También define una constante llamada API que almacena la URL base de la API a la que se realizarán las solicitudes.
import fetch from "node-fetch";
const API = "https://api.escuelajs.co/api/v1";
  1. Función fetchData: Se define una función llamada fetchData que toma una URL como argumento. Esta función realiza una solicitud HTTP asincrónica utilizando fetch para obtener datos desde la URL proporcionada. Luego, espera la respuesta y la convierte en formato JSON antes de devolver los datos.
async function fetchData(urlApi) {
  const response = await fetch(urlApi);
  const data = await response.json();
  return data;
}
  1. Función anotherFunction: Se define otra función llamada anotherFunction que también toma una URL como argumento. Esta función utiliza try...catch para manejar errores potenciales en las solicitudes HTTP.

    • En el bloque try, realiza tres solicitudes HTTP asincrónicas utilizando la función fetchData:

      • La primera solicitud obtiene una lista de productos desde ${urlApi}/products.
      • La segunda solicitud obtiene detalles sobre el primer producto de la lista.
      • La tercera solicitud obtiene detalles sobre la categoría del producto.
    • Luego, imprime la lista de productos, el título del primer producto y el nombre de la categoría.

    • Si se produce algún error en cualquiera de las solicitudes, el bloque catch captura el error y lo muestra en la consola.

const anotherFunction = async (urlApi) => {
  try {
    const products = await fetchData(`${urlApi}/products`);
    const product = await fetchData(`${urlApi}/products/${products[0].id}`);
    const category = await fetchData(
      `${urlApi}/categories/${product.category.id}`
    );

    console.log(products);
    console.log(product.title);
    console.log(category.name);
  } catch (error) {
    console.error(error);
  }
};
  1. Llamada a anotherFunction: Finalmente, se llama a la función anotherFunction pasando la constante API como argumento. Esto inicia el proceso de realizar las solicitudes HTTP y manejar los datos obtenidos.
anotherFunction(API);


En resumen, este código realiza solicitudes HTTP a una API utilizando fetch y maneja los datos obtenidos. Si ocurre algún error en las solicitudes, se captura y muestra en la consola. La estructura asincrónica del código permite realizar múltiples solicitudes de manera eficiente y manejar errores de manera adecuada.

Espero sea de utilidad. 👨‍💻

Me gustó más esta implementación que con las promesas y callbacks.
interesante ver como con distintas herramientas asíncronas se pueden obtener los mismos resultados en JS.

Código usado en clase:

import fetch from "node-fetch";
const API = 'https://api.escuelajs.co/api/v1'

async function fetchData(ulrApi){
    const response = await fetch(ulrApi);
    const data = await response.json();
    return data
}

const anotherFuction = async (ulrApi) => {
    try {
        const products = await fetchData(`${ulrApi}/products`);
        const product = await fetchData(`${ulrApi}/products/${products[0].id}`);
        const category = await fetchData(`${ulrApi}/categories/${product.category.id}`);
        console.log(products);
        console.log(product.title)
        console.log(category.name)
    } catch{
        console.error(error);
    }
}

anotherFuction(API)
const BASE_URL = 'https://api.escuelajs.co/api/v1';

const fetchData = async (urlApi) => {
    try {
        const response = await fetch(urlApi);
        return await response.json();
    } catch (error) {
        console.error(error);
    }
};

const postData = async (urlApi, payload) => {
    try {
        const response = await fetch(urlApi, {
            method: 'POST',
            mode: 'cors', // default cors
            credentials: 'same-origin',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(payload)
        });
        return await response.json();
    } catch (error) {
        console.error(error);
    }
};

const deleteData = async (urlApi) => {
    try {
        const response = await fetch(urlApi, {
            method: 'DELETE',
            mode: 'cors', // default cors
            credentials: 'same-origin',
            headers: {
                'Content-Type': 'application/json'
            }
        })
        return await response.json();
    } catch (error) {
        console.error(error);
    }
}



// ------------------------------------------------------------


async function main() {
    const products = await fetchData(`${BASE_URL}/products`);
    const product = await fetchData(`${BASE_URL}/products/${products[0].id}`);
    const category = await fetchData(`${BASE_URL}/categories/${product?.category?.id}`);
    console.log({ products, product, category });
}

main();
![](https://static.platzi.com/media/user_upload/image-ccde8110-cc1f-4ec5-8129-5ebbfe0eb15f.jpg)
Segun la \[documentación oficial]\(https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Promises) en MDN, recomiendan usar el propio ' .catch ' de las promesas en vez del try... catch, debido a que al igualar la función asíncrona a una variable, esta está devolviendo una promesa en sí, por lo que habría que resolverla para acceder a sus valores. . De aquí que se recomiende lo siguiente según el código de la clase: . ```js const urlAPI = "https://api.escuelajs.co/api/v1/products" async function fetchData (url) { const response = await fetch(url) // keyword ' await ' after we used ' async ' keyword in the function declaration if (!response.ok){ throw new Error(`HTTP error: ${response.status}`) } // in case the fetch failed const data = await response.json() // parsing the response in json format. Also goes with ' await ' keyword return data } // this function returns a response object, that's a promise, therefore we need to resolve it const response_promise = fetchData(urlAPI) // recieving the promise like a synchronous function! response_promise .then(data => console.log(data[0])) .catch(e => console.error(e)) // resolving response_promise object as a promise, handling the errors at the end, that in itself frees us from using try...catch blocks inside the asynchronous function ```
No se si este correcto o no pero yo solo utilice 1 await y para el ejemplo concreto solo realice el llamado a l producto concreto que queria buscar, estó resulto en que el tiempo de ejecucion se acortará hasta la mitad y fuera mucho mas rapido la respuesta. Esto dado que solo me basta 1 await ya que me di cuenta que hasta que no se resuelva este await no se ejecuta el resto del codigo que sigue.const API = 'https://api.escuelajs.co/api/v1'; async function fetchData(urlApi) {    const response = await fetch(urlApi);    const data = await response.json();    return data;    } const anotherFn = async (urlAPI) => {    try {        const allProducts = await fetchData(`${urlAPI}/products`);        const product = allProducts\[0]        const category = product.category;         console.log(product);        console.log(category.name);        console.log(product.title);     } catch (error) {        console.log(new Error(error));    }} anotherFn(API); Por favor corriganme si estoy haciendo una mala practica. ```js const API = 'https://api.escuelajs.co/api/v1'; async function fetchData(urlApi) { const response = await fetch(urlApi); const data = await response.json(); return data; } const anotherFn = async (urlAPI) => { try { const allProducts = await fetchData(`${urlAPI}/products`); const product = allProducts[0] const category = product.category; console.log(product); console.log(category.name); console.log(product.title); } catch (error) { console.log(new Error(error)); } } anotherFn(API); ```
TypeError: Cannot read properties of undefined (reading 'id') at anotherFunction (file:///home/grodo/Documents/js/asincronismo/src/async/challenge.js:14:79) at process.processTicksAndRejections (node:internal/process/task\_queues:95:5) \[Done] exited with code=0 in 2.321 seconds hice el mismo codigo me salio este error copiando el de la clase si corrio pero llevo 2 horas buscando la diferencia entre mi codigo y el del profe si alguien se le ocurre que me diga , mi codigo a continuacion : import fetch from "node-fetch";const API = "https://api.escuelajs.co/api/v1"; async function fetchData(urlApi) { const response = await fetch(urlApi); const data = await response.json(); return data;} const anotherFunction = async (urlApi) => { try { const products = await fetchData(`${urlApi}/products`); const product = await fetchData(`${urlApi}/product/${products\[0].id}`); const category = await fetchData( `${urlApi}/categories/${product.category.id}` ); console.log(products); console.log(product.title); console.log(category.name); } catch (error) { console.error(error); }}; anotherFunction(API);
![](https://static.platzi.com/media/user_upload/image-90c79e2a-f663-4998-a8ea-4e4318882343.jpg)

me gusto la clase

![](https://static.platzi.com/media/user_upload/code-3-59ac9db6-1010-4447-9410-653a992d31f2.jpg)

Me encantó esta clase, no se me hizo tan dificil de entender como las anteriores 😅 estuve intentando poner un tiempo para que se mostraran las solicitudes (me apoyé de chatGPT, aunque estuve cerquita de conseguirlo 😂)

const API = 'https://api.escuelajs.co/api/v1'


async function fetchData(urlApi, ms) {
    const response = await fetch(urlApi)
    const data = await response.json()
    return new Promise(resolve => setTimeout(() => resolve(data), ms));
}

const anotherFunction = async (urlApi) => {
    try {
        const products = await fetchData(`${urlApi}/products`, 5000)
        console.log(products)
        console.log("Todos los productos despues de 5 segundos")

        const product = await fetchData(`${urlApi}/products/${products[0].id}`, 10000)
        console.log(product.title)
        console.log("Primer producto despues de 10 segundos")

        const category = await fetchData(`${urlApi}/categories/${product.category.id}`, 10000)
        console.log(category.name)
        console.log("Categoria despues de 10 segundos")


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

Ahí se los dejo por si quieren intentar

La estructura de control try / catch evalúa si un algoritmo contiene errores, para que el flujo del programa no colapse. Dependiendo del lenguaje, puede cambiar su nombre, pero el concepto será el mismo.

Qué sucede si existe un error en en algoritmo

Recordarás que un algoritmo es una serie de pasos para resolver un problema, sin embargo, estas soluciones no son perfectas, por lo que pueden ocasionar fallos en el programa.

Suponiendo que tenemos el siguiente programa:

"Línea 1"
"Línea 2"
"Línea 3"
"Línea 4"
"Final del programa"

Los programas evalúan línea por línea el código, si no ocurre ningún problema, se ejecutarán todas hasta el final del programa. Sin embargo, si ocurre un error en determinado lugar, el programa se detendrá. Por lo tanto, las líneas que se encuentren después del problema, no serán ejecutadas.

"Línea 1"
"Línea 2"
ERROR

La forma de solucionar esto, es con la estructura try/catch.

Cómo utilizar la estructura try / catch

Envolvemos en el bloque try las líneas de código que podrían provocar un problema, y en caso de que exista un error lo manejaremos en el bloque catch.

"Línea 1"
"Línea 2"
try "Línea 3"
catch
    Mostrar "Algo salió mal..."
"Línea 4"
"Final del programa"

En el caso de que exista un error, el programa ejecutará una serie de sentencias alternativas, sin detener la ejecución de las demás líneas del código.

"Línea 1"
"Línea 2"
"Algo salió mal..."
"Línea 4"
"Final del programa"

Esta estructura es similar a un condicional if-else, pero únicamente con errores.

Para entender un poco más el uso de la estructura try / catch, resolvamos el siguiente problema, de esta manera identificarás cómo utilizarlos.

Cómo manejar errores con try/catch

El algoritmo consiste en dividir dos números. Para esto necesitaremos dos números ingresados por el usuario y realizaremos dicha operación.

"Inicio del programa"
numero1 = _
numero2 = _

"El resultado es: "
resultado = numero1 / numero2
Mostrar resultado
"Fin del programa"

Nuestro programa funciona correctamente si ingresamos cualquier número.

"Inicio del programa"
numero1 = 10
numero2 = 2

"El resultado es: "
5
"Fin del programa"

Sin embargo… ¿Qué sucedería si colocamos que numero2 sea igual a 0?

"Inicio del programa"
numero1 = 10
numero2 = 0

"El resultado es: "
ERROR

¡No puede ser! Nuestro programa colapsó porque no existe la división entre 0. Intentemos resolverlo con la ayuda de try / catch. Si existe un error mostraremos un mensaje.

"Inicio del programa"
numero1 = _
numero2 = _

try"El resultado es: "
    resultado = numero1 / numero2
    Mostrar resultado
catch
    Mostrar "No existe división entre 0"

"Fin del programa"

Ahora comprobemos el algoritmo:

"Inicio del programa"
numero1 = 10
numero2 = 0

"No existe división entre 0"
"Fin del programa"

Ahora nuestro programa no colapsa si existe un error.

Hola quiero aprovechar para que conozcan un concepto interesante "Mock": El concepto de "mock" en desarrollo de software es como utilizar un sustituto o simulador para ciertos componentes o funciones durante las pruebas. En el contexto de llamadas a APIs, un "mock" simula las respuestas que normalmente obtendríamos de un servidor remoto. La idea es evitar depender del comportamiento real de la API y en su lugar, proporcionar datos simulados o predefinidos. En mi código, he creado un archivo llamado "mocks,js" para simular respuestas de tres tipos de llamadas a una `API`: `productsMock` `categoryMock` `productMock` Luego, he implementado una función llamada `getMock` que, dada una `URL`, decide qué tipo de respuesta simular. Esto proporciona flexibilidad y control sobre las respuestas que quiero obtener durante el desarrollo y las pruebas. ```js const categoryMock = () => new Promise(r => r({ json: () => ({ id: 1, name: 'Clothes mock', image: 'https://i.imgur.com/QkIa5tT.jpeg', creationAt: '2023-12-04T12:45:51.000Z', updatedAt: '2023-12-04T12:45:51.000Z' }) }) ); const productMock = () => new Promise(r => r({ json: () => ({ id: 387, title: 'dfwasdfsdfsdfasd', price: 12312, description: 'dsfgfgdfasdasadsdaf', images: [ 'https://www.shipbob.com/wp-content/uploads/2022/06/PRODUCT-RANGE-1536x864.jpg' ], creationAt: '2023-12-05T00:49:14.000Z', updatedAt: '2023-12-05T00:49:14.000Z', category: { id: 1, name: 'Clothes', image: 'https://i.imgur.com/QkIa5tT.jpeg', creationAt: '2023-12-04T12:45:51.000Z', updatedAt: '2023-12-04T12:45:51.000Z' } }) }) ); const productsMock = () => new Promise(r => r({ json: () => [ { id: 387, title: 'Produc mock 1', price: 12312, description: 'dsfgfgdfasdasadsdaf', images: [ 'https://www.shipbob.com/wp-content/uploads/2022/06/PRODUCT-RANGE-1536x864.jpg' ], creationAt: '2023-12-05T00:49:14.000Z', updatedAt: '2023-12-05T00:49:14.000Z', category: { id: 1, name: 'Clothes', image: 'https://i.imgur.com/QkIa5tT.jpeg', creationAt: '2023-12-04T12:45:51.000Z', updatedAt: '2023-12-04T12:45:51.000Z' } }, { id: 390, title: 'Producto mock 2', price: 12312, description: 'dsfgfgdfasdasadsdaf', images: [ 'https://previews.123rf.com/images/stokkete/stokkete2204/stokkete220400134/184550929-mujer-revisando-una-lista-de-compras-y-comprando-productos-en-el-supermercado-su-carrito-de-compras.jpg' ], creationAt: '2023-12-05T00:52:59.000Z', updatedAt: '2023-12-05T00:52:59.000Z', category: { id: 1, name: 'Clothes', image: 'https://i.imgur.com/QkIa5tT.jpeg', creationAt: '2023-12-04T12:45:51.000Z', updatedAt: '2023-12-04T12:45:51.000Z' } }, { id: 391, title: 'Producto Mock 4', price: 20, description: 'clases de front', images: ['https://placeimg.com/640/480/any'], creationAt: '2023-12-05T01:15:30.000Z', updatedAt: '2023-12-05T01:15:30.000Z', category: { id: 1, name: 'Clothes', image: 'https://i.imgur.com/QkIa5tT.jpeg', creationAt: '2023-12-04T12:45:51.000Z', updatedAt: '2023-12-04T12:45:51.000Z' } } ] }) ); export function getMock(url) { if (url.endsWith('/products')) { return productsMock() } if (url.search("\/products") != -1) { return productMock(); } if (url.search("\/categories") != -1) { return categoryMock(); } return new Error('Mock not found') } ```y de está forma la utilizo en el archivo `challenge.js` en el ejercicio de practica: ```js import fetch from "node-fetch"; import { getMock } from "../mock-api/mocks.js"; const API = 'https://api.escuelajs.co/api/v1'; const fetchData = async (urlApi, mock = false) => { const response = !mock ? await fetch(urlApi) : await getMock(urlApi); const data = await response.json(); return data; }; const anotherFn = async (urlApi, mock = false) => { try { const products = await fetchData(`${urlApi}/products`, mock); const product = await fetchData(`${urlApi}/products/${products[0].id}`, mock) console.info('product: ', product.title) const category = await fetchData(`${urlApi}/categories/${product.category.id}`, mock) console.info('category name: ', category.name) } catch (error) { console.error(error) } } anotherFn(API, true); ```**<u>Ventajas de los mocks:</u>** 1- I**ndependencia del Entorno:** No es necesario depender siempre de la API real. Los mocks permiten trabajar de manera aislada. 2- **Control de Escenarios:** Puedo simular diferentes situaciones y respuestas de la API para probar cómo reacciona mi aplicación. 3- **Desarrollo y Pruebas Eficientes:** Al tener respuestas simuladas, puedo desarrollar y probar mi aplicación rápidamente sin depender de la disponibilidad o estabilidad de la API real. 4- **Aislamiento de Errores:** Si hay un problema en la respuesta de la API, puedo cambiar entre la API real y los mocks para aislar rápidamente el origen del problema. **<u>En resumen</u>**, los mocks se utilizan principalmente en pruebas, una área en la que espero aprender más adelante. Sin embargo, en este caso, son útiles cuando tengo una conexión lenta o incluso para continuar trabajando en el desarrollo sin acceso a internet. Esto se logra tomando únicamente los ejemplos de la API real una vez. Nota: Puede mejorar mi archivo "mocks.js" , con mejores técnicas. Inténtalo es genial este concepto. :D

Cómo usar Async/Await con manejo de errores

Podemos manejar errores usando un bloque try catch como este:

const loadData = async () => {
  try {
	  const url = "https://jsonplaceholder.typicode.com/todos/1";
	  const res = await fetch(url);
	  const data = await res.json();
	  console.log(data);
  } catch (err) {
    console.log(err)
  }
};

loadData();

El try-catch anterior solamente manejará errores al obtener los datos, como una sintaxis incorrecta, nombres de dominio incorrectos, errores de red, etc.

Cuando quieras manejar un mensaje de error del código de respuesta de la API, puedes usar res.ok ( res es la variable en la que se almacena la respuesta). Te dará un Boolean con el valor verdadero si el código de respuesta está entre 200 y 209.

const loadData = async () => {
  try {
	  const url = "https://jsonplaceholder.typicode.com/todos/qwe1";
	  const res = await fetch(url);
	  if (res.ok) {
	    const data = await res.json();
	    console.log(data);
	  } else {
	    console.log(res.status); // 404
	  }
  } catch (err) {
    console.log(err)
  }
};

loadData();

// OUTPUT
// 404

Ha dejado de Funcionar en Agosto del 2023

FetchError: request to https://api.escuelajs.co/api/v1/products failed, reason: Hostname/IP does not match certificate's altnames: Host: api.escuelajs.co. is not in the cert's altnames: DNS:*.123emebed.co, DNS:*.akhbarco.com, DNS:*.bieunjoy.com, DNS:*.calscla.org, DNS:*.curiousapiens.com, DNS:*.dramacool1.org, DNS:*.eracristiana.com, DNS:*.evoa.me, DNS:*.forumeg.com, DNS:*.forumil.com, DNS:*.forumps.com, DNS:*.forumsfi.com, DNS:*.forumstw.com, DNS:*.hch989.com, DNS:*.
Pienso que el await/sync fue la forma mas simple y corta de trater los elementos comparandola a las promesas y callbacks

Sobra el await que he comentado ya que response.json() no devuelve una promesa.

async function fetchData(urlApi){
    const response = await fetch(urlApi);
    const data = /*await*/ response.json();
    return data;
}

16/26 Try and catch
Imagina que estas jugando basketball. Normalmente se espera que la pelota pase por el aro sin problemas pero algunas veces la pelota puede ir en una dirección inesperada y no entrar por el aro.

En la programación try and catch son bloques que te permiten manejar errores de una manera controlada. Puedes intentar ejecutar un bloque de código en el bloque try, y si ocrurre algun error, puedes capturarlo y manejadrlo en el bloque catch.

try {
  // Bloque de código que puede generar un error
  console.log(variableInexistente);
} catch (error) {
  // Bloque de código para manejar el error
  console.error('Ha ocurrido un error:', error);
}

Tenemos un bluqe try que contiene una línea de código que intenta acceder a una variable inexistente (variableInexistente) esto generará un error, ya que la variable no está definida.

Si ocurre un error dentro del bloque try la ejecución del código se detendra en ese punto y pasará al bloque catch. El bloque catch contiene código para manejar el error. En este caso, utilizamos console.error() para imprimir un mensaje de errror en la consola, junto con el error capturado (error).

Utilizando try y catch se puede manejar posibles errores en tu programa de manera controlada. Es como intentar lanzar una pelota al aro, pero si la pelota va en una dirección inesperada, puedes atraparla y manejarla adecuadamente

Es importante mencionar que el uso de try y catch es especialmente útil para evitar que los errores detengan la ejecución de tu programa y te permite manejarlos de forma adecuada, brindando una respuesta o solución alternativa cuando sea necesario.

Version top-level await:

 import fetch from "node-fetch";

 const API = "https://api.escuelajs.co/api/v1"

 const products = await fetch(`${API}/products`).then((data) => data.json())
 const product = await fetch(`${API}/products/${products[210].id}`).then((data) => data.json())
 const category = await fetch(`${API}/categories/${product.category.id}`).then((data) => data.json())

 console.log(products)
 console.log(product.title)
 console.log(category.name)

TRY CATCH IMPORTANCIA

try y catch permite manejar si la ejecución ha sido satisfactoria o errónea. Es similar a .then y .catch en promesas. Es importante su uso ya que si hay un error en esa petición por un error tuyo al hacer la lógica o un error de sintaxis, la ejecución se va a detener por completo y todo se caerá.

Entonces si hay un error, la información de ese error se va a catch y luego puedes usar ese parámetro para ver el error PERO sin que toda la app se caiga.

🍃 Este código también trabaja con funciones asíncronas y promesas en JavaScript, en este caso se utiliza la palabra clave async para marcar la función fetchData como asíncrona, y await para esperar la respuesta de la solicitud fetch.

Aquí te explico el código paso a paso:

  1. Se importa el módulo node-fetch para utilizar la función fetch en Node.js y se define la constante API con la URL base de la API a la que se va a realizar la solicitud.

    import fetch from "node-fetch";
    const API = "https://api.escuelajs.co/api/v1";
    
  2. Se define la función fetchData como asíncrona. Dentro de la función, se utiliza await para esperar la respuesta de la solicitud fetch, y luego se usa await nuevamente para obtener los datos en formato JSON. Finalmente, se retorna el objeto JSON.

    async function fetchData(urlAPI) {
    	const response = await fetch(urlAPI);
    	const data = await response.json();
    	return data;
    }
    
  3. Se define la función anotherFunction como asíncrona, la cual recibe un parámetro urlAPI. Dentro de esta función, se utiliza un bloque try...catch para manejar cualquier error que se pueda producir durante la ejecución. Se utiliza await para esperar a que se resuelva la promesa retornada por la función fetchData para obtener los productos, el primer producto y la categoría del primer producto. Luego, se muestra en la consola los objetos obtenidos.

    const anotherFunction = async (urlAPI) => {
    	try {
    		const products = await fetchData(`${urlAPI}/products`);
    		const product = await fetchData(`${urlAPI}/products/${products[0].id}`);
    		const category = await fetchData(
    			`${urlAPI}/categories/${product.category.id}`
    		);
    
    		console.log(products);
    		console.log(product.title);
    		console.log(category.name);
    	} catch (error) {
    		console.log(error);
    	}
    };
    
  4. Se llama a la función anotherFunction con la constante API como parámetro, para realizar la solicitud a la API y mostrar los resultados en la consola.

    anotherFunction(API);
    

En resumen, este código demuestra cómo trabajar con funciones asíncronas y promesas en JavaScript utilizando async y await para manejar las solicitudes fetch. La función fetchData utiliza await para esperar la respuesta de la solicitud fetch y luego obtener los datos en formato JSON. La función anotherFunction utiliza await para esperar a que se resuelvan las promesas retornadas por la función fetchData y mostrar los resultados en la consola.

Este curso debía estar en node.js no es JavaScript. Solo están confundiéndonos en lugar de enseñar.

Extrañare mi espagueti, me hacía sentir que sabía mucho.

Apunte en Notion

La palabra reservada async sirve para que la función sea una función asincrona. Mientras que await se usa para decirle a javascript que queremos que espere a que se ejecuta una línea de código determinada antes de pasar a la siguiente línea. En otras palabras, si no usamos la palabra reservada await en la línea después del “try”, lo que haría javascript es, al ser fetchData una función asíncrona, saltarse dicha línea (delegarla) y pasar a la siguiente que es " const product = await fetchData(${API}/products/${products[0].id});"

const anotherFunction = async (urlApi) => {
  try {
    const products = await fetchData(`${API}/products`);
    const product = await fetchData(`${API}/products/${products[0].id}`);
    const category = await fetchData(`${API}/categories/${product.category.id}`);

    console.log(products[0]);
    console.log(product.title);
    console.log(category.name);
  } catch (error) {
    console.error(error);
  }
}

sigo teniendo problemas con fetch, ya elimine node, lo volvi a instalar y sigue con ele mismo error en mi consola wsl2

Excelente clase Oscar

esta clase me gustó, pude ver que es mucho más fácil entender y usar async await que Promise

Mi código con algunas mejoras como que nos reporte el código de la respuesta de la API y el número de productos.

import fetch from 'node-fetch';
const API = 'https://api.escuelajs.co/api/v1';

async function fetchData(urlApi){
    const response = await fetch(urlApi);
    const data = await response.json();
    console.log(`Código respuesta :${response.status}`)
    return data
}

const anotherFunction = async (urlApi) => {
    try {
        const products = await fetchData(`${urlApi}/products`);
        const product = await fetchData(`${urlApi}/products/${products[0].id}`);
        const category = await fetchData(`${urlApi}/categories/${product.category.id}`);

        console.log(`Productos: ${products.length}`)
        console.log(`Titulo primer producto: ${product.title}`)
        console.log(`Categoria: ${category.name}`)
    } catch (error) {
        console.error(error)
    }
}

anotherFunction(API);

Excelente curso me encanta la práctica de los temas, y con estos conocimientos se puede primero consumir servicios web y lo mejor usar buenas prácticas y sintaxis moderna de JavaScript para refactorizar proyectos existentes!!

para practicar me puse hacer como crear una categoria y un producto con async-await.
Aqui les dejo el codigo.

import fetch from "node-fetch";

const API = 'https://api.escuelajs.co/api/v1';

async function create(url, data) {
    const response = await fetch(url, {
        method: 'POST',
        mode: 'cors',
        credentials: 'same-origin',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
    });
    return await response.json();
}

const onError = (error) => console.log(error);

const onExecuteCategory = async (url, data) => {
    try {
        const category = await create(`${url}/categories`, data);
        console.log(category)
    } catch (error) {
        onError(error);
    }
}

let category = {
    name: "New Category",
    image: "https://placeimg.com/640/480/any"
};
onExecuteCategory(API, category);

const onExexuteProduct = async (url, data) => {
    try {
        const product = await create(`${url}/products`, data)
        console.log(product)
    }catch (error) {
        onError(error);
    }
}

const product = {
    title: 'Sergio product',
    price: 1000,
    description: 'A description',
    categoryId: 1,
    images: ["https://placeimg.com/640/480/any"]
};
onExexuteProduct(API, product);
import fetch from "node-fetch";

const API = 'https://api.escuelajs.co/api/V1'

async function fetchData(urlApi){
  const response = await fetch(urlApi);
  const data = await response.json();
  return data;
}

const anotherFn = async(urlApi)=>{
  try {
    const products = await fetchData(`${urlApi}/products`);
    const product = await fetchData(`${urlApi}/products/${products[0].id}`);
    const category = await fetchData(`${urlApi}/categories/${product.category.id}`);

    console.log(products);
    console.log(product.title);
    console.log(category.name);

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

anotherFn(API);

Buenas! Dejo mi codigo comentado, creo que podria ser de utilidad para entender como funcionan las peticiones con ASYNC y AWAIT

import fetch from "node-fetch";
const API = `https://api.escuelajs.co/api/v1`;

// Creo la funcion "fetchData" la cual es Asincrona/Async y recibe de parametro la urlAPI + sus especificaciones como un producto en particular (${products[0].id}).
// Dentro de la funcion, se ejecuta una constante llamada "Response" que es una funcion "FETCH" la cual busca y espera/AWAIT los datos de la API.
// Una vez traidos los datos de la API de "Response", creamos una constante "data" la cual espera/AWAIT los resultados de la PROMESA FETCH para transformarlos a .json
// Ya transformados los datos a .json , RETORNAMOS osea DEVOLVEMOS esos datos con "return data".
// BASICAMENTE ESTA FUNCION BUSCA LOS DATOS, LOS TRANSFORMA A JSON y TE LOS DEVUELVE YA RETORNADOS.
async function fetchData(urlApi){
    const response = await fetch(urlApi);
    const data = await response.json();
    return data;
};


// Creamos una funcion ASINCRONA que hara las PETICIONES HTTP a "todos los productos, un producto en particular y a la categoria de este producto"
// Dentro de esta funcion DEFINIMOS 2 BLOQUES DE CODIGO: 
// TRY - Dentro del bloque TRY ocurrira toda la logica de nuestra aplicacion, es decir es donde haremos las "Peticiones" a la API, a traves de la funcion ya establecida "fetchData" que tendra que ser esperada/Await. 
// CATCH - Dentro del bloque CATCH ocurrira el "REJECT" osea es quien "atrapara" un error en caso de que exista.
// BASICAMENTE CON ESTA FUNCION REALIZAMOS LOS LLAMADOS CORRESPONDIENTES y IMPRIMOS LOS RESULTADOS EN CONSOLA.
const anotherFunction = async (urlApi) => {
    try{
        const products = await fetchData(`${urlApi}/products`)
        const product = await fetchData(`${urlApi}/products/${products[0].id}`)
        const category = await fetchData(`${urlApi}/categories/${product.category.id}`)

        console.log(products);
        console.log(product.title);
        console.log(category.name);

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

// Llamamos a nuestra funcion asincrona "anotherFunction" la cual dentro llama a nuestra otra funcion "fetchData" que a sus vez llama al metodo "Fetch" para realizar las peticiones.
anotherFunction(API);

Probando el pagination y realizando llamadas concurrentes obtuve el siguiente codigo

Con 200 productos no hay mucha diferencia en los tiempos

/**
 * Compare loading the products with and without pagination
 * Run the script from console twice:
 *   - line 93 commented, check time
 *   - line 36 commented, check time (with pagination and all promises running)
 *
 * Execute 'time npm run [script-name]'
 *
 * Compare time, make some changes, and compare again, have fun!!
 *
 * Dont forget 'console.log' works with std output in console, this can make it seems slower
 */

import fetch from "node-fetch";
const API = 'https://api.escuelajs.co/api/v1';

async function fetchData(urlAPI) {
    console.log(`async fetchData(${urlAPI}) start`);
    const response = await fetch(urlAPI);
    console.log(`async fetchData(${urlAPI}) end`);
    return response.json();
}

const retrieveAll = async urlAPI => {
    try {
        console.log(`async retrieveAll(${urlAPI}) start`);
        const products = await fetchData(`${urlAPI}/products`);
        console.log(`${products.length} products retrieved!!`);
    } catch(err) {
        console.error(error);
    }finally {
        console.log(`async retrieveAll(${urlAPI}) end`);
    }
}

//retrieveAll(API); // WITHOUT PAGINATION

// For this Im going to asume I have a method to know the number of products
// If I try to retrieve chunks instead of retrieving all

const retrieveWithPagination = (urlAPI, offset, limit) => {
    /*
     * this function is just a wrapper, it does nothing more than
     * encapsulate and extract the:
     *     "fetchData(`${urlAPI}/products?offset=${offset}&limit=${limit}`)"
     * from retrieveChunks method
     *
     * You can replace the "retrieveWithPagination(API, offset, limit)"
     * and erase this method if you want
     */
    try {
        const url = `${urlAPI}/products?offset=${offset}&limit=${limit}`;
        return fetchData(url);
    } catch(err) {
        console.error(error);
    }
}

function retrieveChunks() {
    // TODO: refactor, use try..catch
    const totalProducts = 210;
    const defaultLimit = 60;
    const productsPromises = [];

    for (let i = 0; i < totalProducts; i += defaultLimit) {
        const offset = i;
        if (offset >= totalProducts) break;

        const limit = offset + defaultLimit < totalProducts ? defaultLimit : totalProducts - offset;
        productsPromises.push(retrieveWithPagination(API, offset, limit));
    }

    Promise.all(productsPromises)
        .then(productsPromisesResolved => {
            let products = []
            // forEach is not recommended for async but in this case
            // Im doing Promise.all() so if there are no errors
            // all the promises will resolve before getting here
            productsPromisesResolved.forEach(chunk =>
                products = [
                    ...products,
                    ...chunk
                ]
            );
            console.log(`${products.length} products retrieved!!`);
        })
        .catch(error => {
            console.error(error);
            return [];
        });
}

retrieveChunks(); // WITH PAGINATION

ejemplo muy completo y chevre que se muestra como hacer con function normal y con arrow function

import fetch from "node-fetch";
const API = 'https://api.escuelajs.co/api/v1';

async function fetchData(urlApi){
    const response = await fetch(urlApi);
    const data = await response.json()
    
    return data;
}

const anotherFuncion = async(urlApi) =>{
    try{
        const products = await fetchData(`${urlApi}/products`);
        const product = await fetchData(`${urlApi}/products/${products[8].id}`);
        const category = await fetchData(`${urlApi}/categories/${product.category.id}`);

        console.log(products);
        console.log(product.title);
        console.log(category.name);


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

 anotherFuncion(API);

excelente clase

⭐ Try & Catch

Nos permite crear un bloque a intentar (try), y otro por si falla o se produce una excepción (catch).

const anotherFuction = async (urlAPI) => {
    try {
        const products = await fetchData(`${urlAPI}/products`);
        const product = await fetchData(`${urlAPI}/products/${products[0].id}`);
        const category = await fetchData(`${urlAPI}/categories/${product.category.id}`);
        console.log(products);
        console.log(product.title)
        console.log(category.name)
    } catch{
        console.error(error);
    }
}

anotherFuction(API)