No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Try and catch

16/26
Recursos

Aportes 49

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 鈥減rincipal鈥 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 鈥渁notherFunction鈥 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 鈥減roducts鈥 ejecutamos la funcion 鈥減rincipal鈥 en este caso 鈥渇etchData鈥, le colocamos la url base almacenada en 鈥渦rlApi鈥 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 鈥減roduct鈥 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 鈥渄esglosando鈥 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 (鈥渄esglosado鈥 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 鈥渞esolve鈥 con try. Y otro bloque para lo que seria el 鈥渞eject鈥 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 鈥榝etchData鈥 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

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();

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);

* *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.

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/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聽condicionalif-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

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. 馃懆鈥嶐煉

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)