Async JS: Guía completa sobre código asíncrono РParte #2

Retomamos esta serie sobre JavaScript as√≠ncrono. Si acabas de aterrizar aqu√≠, te recomiendo que veas la parte #1 antes, ya que voy a utilizar todos los acr√≥nimos all√≠ definidos. ūüėä

C√≥mo usar las callback functions ‚Äčdentro de una HTTP Request‚Äč‚Äč‚Äč‚Äč‚Äč

Lo habitual cuando hacemos una ‚Äčrequest ‚Äčes darle forma de funci√≥n y guardarla en una variable para as√≠ poder llamarla cuando la necesitemos. Adem√°s, eso la hace re-utilizable, lo que es una buena pr√°ctica. Como estamos trabajando con JSONPlaceholder para obtener una lista de ‚Äčto do's (‚Äčtareas)‚Äč‚Äč, vamos a darle el nombre a la variable de getToDos.

const getToDos = () => {
    const request = new XMLHttpRequest();

    request.addEventListener('readystatechange', () => {
        // console.log(request);
        // console.log(request.readyState);
        if (request.readyState === 4 && request.status === 200) {
            console.log(request, request.responseText);
        } else if (request.readyState === 4) {
            console.log('ooops...we could not fetch the data');
        }
    });

    request.open('GET', 'https://jsonplaceholder.typicode.com/todos');
    request.send();
};

Ahora, para hacer nuestra ‚Äčrequest, ‚Äčsolo tendr√≠amos que invocar la funci√≥n:‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč

getToDos();

y recibir√≠amos la response igual que antes.

Por ahora todo lo que estamos haciendo es imprimir siempre el ‚ÄčresponseText, ‚Äčporque as√≠ lo hemos especificado:

console.log(request, request.responseText);

Ser√≠a m√°s √ļtil si, en lugar de tener ese console.log, ‚Äčle pas√°ramos una ‚Äčcallback function, ‚Äčcuyo comportamiento podr√≠amos gestionar independientemente y as√≠ hacer nuestra ‚Äčrequest ‚Äčm√°s flexible. Entonces, cada vez que llam√°semos a ‚ÄčgetToDos(), ‚Äčpodr√≠amos especificar una ‚Äčcallback function ‚Äčdistinta, adaptada a nuestras necesidades. ¬°Vamos a ello! ūüĎ©‚ÄćūüíĽ

1. Especificamos una ‚Äčcallback function ‚Äčcomo primer argumento del ‚ÄčgetToDos().‚Äč‚Äč

‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč2. Como le estamos pasando un par√°metro al ‚ÄčgetToDos, ‚Äčeso significa que tenemos que avisarle de que va a recibir un par√°metro. Lo llamamos ‚ÄčcallbackFunc, ‚Äčpor ejemplo.

3. Dentro de nuestra ‚Äčrequest, ‚Äčen lugar de escribir un ‚Äčconsole.log, ‚Äčle pasamos nuestra callbackFunc()Vamos a probarlo haciendo un console.log dentro de la callback function de getToDos().

const getToDos = (callbackFunc) => {
    const request = new XMLHttpRequest();

    request.addEventListener('readystatechange', () => {
        // console.log(request);
        // console.log(request.readyState);
        if (request.readyState === 4 && request.status === 200) {
            // console.log(request, request.responseText);
            callbackFunc();
        } else if (request.readyState === 4) {
            // console.log('ooops...we could not fetch the data');
            callbackFunc();
        }
    });

    request.open('GET', 'https://jsonplaceholder.typicode.com/todos');
    request.send();
};

getToDos(() => {
    console.log('callback function fired!');
});

ūü§Ē Pero si ahora cometemos alg√ļn tipo de error en el API endpoint, la callback function se seguir√≠a disparando, porque evidentemente le estamos pasando la misma callback a ambos casos del if / else statement. Lo suyo ser√≠a pasarle la informaci√≥n de la response en el bloque if  y cualquier error que ocurra en el bloque else:

    request.addEventListener('readystatechange', () => {
        if (request.readyState === 4 && request.status === 200) {
            callbackFunc(// pass the data);
        } else if (request.readyState === 4) {
            callbackFunc(// pass the error);
        }
    });

Para hacer esa verificaci√≥n de cu√°ndo estamos ante una obtenci√≥n de datos correcta y cu√°ndo ante un error, configuramos nuestra callback function en el getToDos().

4. La callback function va a aceptar dos par√°metros: err data. ‚ÄčEs una convenci√≥n que primero le pasemos el error y segundo la informaci√≥n. ūü§ď

getToDos((err, data) => {
    console.log('callback function fired!');
});

5. Personalizamos cada callbackFunc. El primer if statement contempla el caso de que todo haya salido bien. Por tanto, el par√°metro err ser√≠a undefinedEl segundo par√°metro (data), ser√≠a el responseText. 

‚Äč‚ÄčEn el block del ‚Äčelse statement, la ‚ÄčcallbackFunc ‚Äč‚Äčtambi√©n espera un error como primer par√°metro, y este es el bloque que gestiona si algo ha salido mal, as√≠ que le pasamos un mensaje tipo "algo sali√≥ mal, no se ha podido obtener los datos". Como segundo par√°metro le pasamos ‚Äčundefined, ‚Äčya que en este bloque no se ha podido recibir el ‚ÄčresponseText. 

        request.addEventListener('readystatechange', () => {
            if (request.readyState === 4 && request.status === 200) {
                callbackFunc(undefined, request.responseText);
            } else if (request.readyState === 4) {
                callbackFunc('no se han podido obtener los datos', undefined);
            }
        });

‚Äč6. Hacemos un ‚Äčconsole.log ‚Äčdel ‚Äčerr ‚Äčy de la ‚Äčdata ‚Äčpara ver si vamos por el buen camino.

getToDos((err, data) => {
    console.log('callback function fired!');
    console.log(err, data);
});

Prueba a hacer la ‚Äčrequest ‚Äčcon un ‚ÄčAPI endpoint ‚Äčcorrecto y con uno incorrecto, y ver√°s la diferencia. ūüėŹ

7. Sabiendo esto, podemos comprobar si tenemos o no un error, y hacer cosas distintas seg√ļn el caso. Vamos simplemente a imprimir por consola el error y los datos.

getToDos((err, data) => {
    console.log('callback function fired!');
    // console.log(err, data);
    if (err) {
        console.log(err);
    } else {
        console.log(data);
    }
});

Y con esta comprobaci√≥n, ahora s√≥lo se nos imprimir√° el mensaje de error en caso de que el ‚ÄčAPI endpoint ‚Äčsea incorrecto, o recibiremos los datos en caso contrario. ūüĎĆ

8. Si ahora hacemos una prueba para ver si verdaderamente este código asíncrono no bloquea nuestra secuencia de ejecución, tendríamos un resultado satisfactorio.

console.log(1);
console.log(2);

getToDos((err, data) => {
    console.log('callback function fired!');
    // console.log(err, data);
    if (err) {
        console.log(err);
    } else {
        console.log(data);
    }
});

console.log(3);
console.log(4);

En tu consola ver√°s que los console.log se han impreso primero, ya que la request se ha ejecutado en paralelo y finalmente resuelto, siendo as√≠ la √ļltima parte en imprimirse en la consola. ūüĎć

Cómo trabajar con JSON data

Sabemos que el formato JSON es el formato en el que la mayor√≠a de APIs nos devuelven informaci√≥n cuando se la solicitamos por medio de una HTTP request. Este formato tiene pinta de una JS array lleno de JS objects, pero si nos fijamos, es en realidad un string gigante. 

JSON = JavaScript Object Notation

Es un ‚Äčstring ‚Äčporque esta es la √ļnica manera de transferir datos entre un servidor y un navegador. 

ūüĎ©‚ÄćūüŹę Vamos a aprender a convertir la informaci√≥n de formato JSON a un verdadero objeto de JS. Para esto, existe un built-in object en JS llamado JSON, que, junto a un m√©todo llamado parse()hace justo lo que necesitamosVamos a probarlo en nuestro sandbox.js.

1. Dentro del bloque if de nuestra request, creamos una variable llamada data que almacenar√° el valor de responseText, convertido a un array de objetos. Para ello usamos el m√©todo parse() sobre JSON y le pasamos el JSON string que queramos convertir en un objeto de JS (el responseText).

2. En la ‚ÄčcallbackFunc ‚Äčdel bloque ‚Äčif ‚Äčle pasamos la variable ‚Äčdata ‚Äčque acabamos de crear, en lugar del ‚ÄčresponseText. 

            if (request.readyState === 4 && request.status === 200) {
                const data = JSON.parse(request.responseText);
                callbackFunc(undefined, data);
            } else if (request.readyState === 4) {
                callbackFunc('no se han podido obtener los datos', undefined);
            }

Si ahora guardas y vas a tu consola, ¬°ver√°s que tenemos un JS array ‚Äčlleno de objetos! ūüĎŹ

> (200) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, …]

M√°s adelante exploraremos c√≥mo acceder a esos objetos y a sus key-value pairs. Por el momento, hay otra cosa que podemos hacer: crear nuestro propio archivo JSON. ūüí™

3. En la misma carpeta que nuestro index.html sandbox.js (al mismo nivel) creamos un archivo llamado toDos.json. Sabemos que un archivo JSON es un √ļnico string, pero no por ello necesitamos escribir nuestro c√≥digo entre comillas " ", ya que nuestro editor sabe que es un archivo JSON.

ūüĎÄ La diferencia cuando escribimos c√≥digo JSON es que todos nuestros key-values tienen que estar entre comillas dobles. Para los n√ļmeros, no es necesario:

[
    {
        "key": "value",
        "key": "value",
        "key": 33,
        "key": 30,
    }
]

4. Siguiendo estas indicaciones, vamos a a√Īadir las primeras l√≠neas de c√≥digo a nuestro archivo JSON, imaginando que estamos creando una base de datos con listas de tareas de diferentes personas. ūüďĚ

[
    {
        "play dungeons & dragons": "Will"
    },
    {
        "buy bat": "Steve"
    },
    {
        "call Ms. Wheeler": "Billy"
    }
]

5. Volvemos al sandbox.js e intentamos hacer nuestra request un API endpoint distinto. Concretamente, a nuestro archivo JSON, usando un relative path. 

    request.open('GET', 'toDos.json');

¬°Y ya lo tenemos! En nuestra consola podemos ver el c√≥digo JSON, convertido en un array con 3 objetos dentro. ūüéČ

¬ŅQu√© demonios es el callback hell?

 Hasta ahora s√≥lo estamos llamando a la funci√≥n ‚ÄčgetToDos ‚Äčuna vez, y s√≥lo solicitando informaci√≥n a un ‚ÄčAPI endpoint. ‚ÄčEn la vida real, lo normal es que hagamos ‚Äčhttp requests ‚Äča m√°s de una API, por tanto, vamos a ver c√≥mo tratar esos casos. 

1. Creamos una carpeta al nivel del index.html a la que llamamos toDos. Dentro creamos tres archivos JSON, donde cada uno contiene una lista de tareas de una persona distinta. 

Estructura de archivos:

  • ūüďĀtoDos
    • ūüďĚbilly.json
    • ūüďĚmike.json
    • ūüďĚwill.json
  • ūüďĚindex.html
  • ūüďĚsandbox.js 
[
  { "task": "call Ms. Wheeler", "author": "Billy" },
  { "task": "recruit people for the dark side", "author": "Billy" },
  { "task": "clean swimmingpool", "author": "Billy" }
]
[
  { "task": "kill Demogorgon", "author": "Mike" },
  { "task": "find Eleven", "author": "Mike" },
  { "task": "buy a new bike", "author": "Mike" }
]
[
  { "task": "play dungeons & dragons", "auhtor": "Will" },
  { "task": "escape from Demogorgon", "author": "Will" },
  { "task": "go to the arcade", "author": "Will" }
]

Lo que queremos es obtener la información de los tres archivos en orden, es decir, primero las tareas de Billy, luego las de Mike y finalmente las de Will.

Este concepto de solicitar la informaci√≥n en cierto orden es muy com√ļn cuando trabajamos con APIs, porque es normal que queramos obtener cierta informaci√≥n de una API primero para luego usarla y hacer otra http request, por ejemplo.

Si buscamos en nuestro c√≥digo, podemos localizar que el momento en el que una primera ‚Äčrequest ‚Äčestar√≠a completada ser√≠a cuando hacemos el ‚Äčconsole.log ‚Äčde ‚Äčdata: ‚Äč‚Äč‚Äč‚Äč

getToDos((err, data) => {
    console.log('callback function fired!');
    if (err) {
        console.log(err);
    } else {
        console.log(data);
    }
});

As√≠ que ese ser√≠a un buen lugar para hacer nuestra segunda ‚Äčhttp request. 

‚Äč‚ÄčAhora, nuestro ‚ÄčAPI endpoint ‚Äčapunta al archivo ‚ÄčtoDos.json. ‚ÄčNosotros queremos recibir la informaci√≥n de los otros tres archivos JSON, pero no podemos escribir el ‚Äčrelative path ‚Äčde ninguno de √©stos, porque as√≠ no estar√≠amos escribiendo c√≥digo din√°mico, sino est√°tico (‚Äčhardcoded). 

2. As√≠ que lo que hacemos es pasarle otro par√°metro a la funci√≥n ‚ÄčgetToDos(), ‚Äčllamado ‚ÄčtasksList. Se lo pasamos tambi√©n al preparar la ‚Äčrequest ‚Äčcomo segundo argumento, sustituyendo as√≠ el ‚ÄčAPI endpoint ‚Äčque ten√≠amos ‚Äčhardcoded. 

3. Al llamar a la funci√≥n ‚ÄčgetToDos(), ‚Äčque ahora recibe dos argumentos, le pasamos como primer argumento el ‚Äčrelative path ‚Äčde uno de nuestros archivos JSON, del que queramos recibir la informaci√≥n primero. Por ejemplo, de mike.json.

4. Quitamos el bloque ‚Äčif / else ‚Äčde momento, y s√≥lo hacemos un ‚Äčconsole.log ‚Äčde ‚Äčdata, ‚Äčpara comprobar que efectivamente s√≥lo nos devuelve la informaci√≥n de ‚Äčmike.json.‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč

const getToDos = (tasksList, callbackFunc) => {
    const request = new XMLHttpRequest();

    request.addEventListener('readystatechange', () => {
        if (request.readyState === 4 && request.status === 200) {
            const data = JSON.parse(request.responseText);
            callbackFunc(undefined, data);
        } else if (request.readyState === 4) {
            callbackFunc('no se han podido obtener los datos', undefined);
        }
    });

    request.open('GET', tasksList);
    request.send();
};

getToDos('toDos/mike.json', (err, data) => {
    // console.log('callback function fired!');
    console.log(data);
});

Si ahora vas a tu consola, ver√°s que s√≥lo has recibido la informaci√≥n sobre Mike. ¬°Chachi! ūü§ó

5. Como ya estamos seguros de que en este punto hemos recibido la informaci√≥n de Mike, ahora queremos recibir la informaci√≥n de Billy. Y eso deber√≠amos hacerlo justo despu√©s de recibir la informaci√≥n de Mike. 

getToDos('toDos/mike.json', (err, data) => {
  console.log(data);
  // solicitar info Billy aqu√≠
});

Siguiendo el mismo patrón, una vez estemos seguros de que hemos recibido la información de Billy, ya podríamos solicitar la información de Will.

getToDos('toDos/mike.json', (err, data) => {
    console.log(data);
    getToDos('toDos/billy.json', (err, data) => {
        console.log(data);
        getToDos('toDos/will.json', (err, data) => {
            console.log(data);
        });
    });
});

Aunque esto funciona perfectamente, empieza a convertirse en un c√≥digo realmente complejo y terriblemente dif√≠cil de mantener a la larga. Por no hablar de que, si a√Īadi√©semos 10 ‚Äčcallbacks ‚Äčm√°s, tendr√≠amos un c√≥digo en forma de pir√°mide totalmente insostenible. ūüėĪ

Esto es lo que se llama el callback hell, aunque a m√≠ me gusta llamarlo el tri√°ngulo del infierno. As√≠ sucede el ‚Äčcallback hell: ‚Äčanidando‚Äč‚Äč callbacks dentro de callbacks. ūüėĶ

callback hell ejemplo

Qu√© son las ‚Äčpromises ‚Äčy c√≥mo usarlas‚Äč‚Äč

Para lidiar con el callback hell y librarnos de √©l, podemos usar una herramienta m√°s moderna de JS: las promesas (promises). Para entender bien el concepto, vamos a hacer un peque√Īo ejemplo y luego aplicaremos lo aprendido a nuestra ‚ÄčgetToDos().

Ejemplo con conceptos b√°sicos

1. Comentamos todo el c√≥digo del ‚Äčcallback hell ‚Äčo lo borramos directamente, porque no nos va a hacer falta m√°s. 

2. Creamos una variable llamada getSomething, que guardar√° una funci√≥n encargada de hacer una http request. Parecido a lo que hace nuestra funci√≥n getToDos(). ‚ÄčCuando utilizamos ‚Äčpromises, ‚Äčlo primero que debemos hacer es un ‚Äčreturn ‚Äčde una ‚Äčnew Promise. 

const getSomething = () => {
    return new Promise();
};
‚ÄčUna promise es algo que va a tardar cierto tiempo en ejecutarse, y cuando lo haga, lo har√° de dos maneras posibles: si se cumple lo que hab√≠amos previsto, (por ejemplo, obtener cierta informaci√≥n), la promesa ser√° resuelta (resolved), en caso contrario, la promesa ser√° rechazada (rejected).

Aqu√≠ un esquemita aclarativo: 

esquema estructura promises

3. La promise acepta como par√°metro una funci√≥n. Dentro de esa funci√≥n es donde hacemos la http request. Por ahora no vamos a hacer una request, solo vamos a simularla para no complicar el ejemplo. 

const getSomething = () => {
    return new Promise(() => {
        
    });
};

Los conceptos de resolve reject son parecidos a cuando hac√≠amos un if / else statement para comprobar si la request hab√≠a funcionado correctamente y sin errores. Con la ventaja de que en una promise, estos dos m√©todos (resolve reject) vienen por defecto en el objeto promise, ‚Äčcomo parte de la JavaScript promise API‚Äč‚Äč. ūüĎĆ  

4. Y eso es lo que le pasamos a la funci√≥n de nuestra promise como par√°metroSi hemos recibido bien los datos de nuestra request, ejecutaremos el m√©todo resolve() y le pasaremos los datos. Pero como por ahora no tenemos datos porque estamos haciendo una simulaci√≥n, le pasamos un string diciendo algo tipo 'datos recibidos'.

5. Sin embargo, si hubiese un error, llamar√≠amos al m√©todo reject() y le pasar√≠amos el error. Como tampoco tenemos un error definido, le pasamos un string diciendo algo tipo 'error en la recepci√≥n de los datos'.

const getSomething = () => {
    return new Promise((resolve, reject) => {
        resolve('datos recibidos');
        reject('error en la recepción de los datos');
    });
};

6. Normalmente har√≠amos todo esto dentro de un if / else statement, comprobando si todo ha salido bien, ejecutando el resolve, o ejecutando el reject si algo ha ido mal. Pero por motivos de simplicidad, vamos a hacer una posibilidad cada vez. Probamos primero con el m√©todo ‚Äčresolve(), ‚Äčcomentando el ‚Äčreject().‚Äč‚Äč

7. Si ahora llamamos a la funci√≥n getSomething(), √©sta devuelve una promise, que va a ejecutar el bloque de resolve o el de reject dependiendo de c√≥mo haya ido la request. Aqu√≠ es donde vinculamos dos m√©todos a la funci√≥n: el then y el catch:

getSomething()
    .then()
    .catch();

8. Al m√©todo then() le pasamos una funci√≥n que se ejecutar√° cuando la promise haya salido bien (resulte en resolve). Lo que significa que recibe por par√°metro la informaci√≥n que se haya recibido en el m√©todo resolve. Si ahora hacemos un console.log de esa informaci√≥n, veremos que es justamente la informaci√≥n que trae el m√©todo resolve (la frase 'datos recibidos').

const getSomething = () => {
    return new Promise((resolve, reject) => {
        resolve('datos recibidos');
        // reject('error en la recepción de los datos');
    });
};

getSomething()
    .then(data => {
        console.log(data);
    })

Y esa es la frase que deber√≠amos ver en nuestra consola. ūüßź

9. Si probamos a comentar el resolve() y a descomentar el reject, se dispar√° la callback function vinculada a otro m√©todo llamado catchAh√≠ es donde tenemos que especificar qu√© hacer con el error. En este caso, simplemente lo imprimimos por consola. 

const getSomething = () => {
    return new Promise((resolve, reject) => {
        // resolve('datos recibidos');
        reject('error en la recepción de los datos');
    });
};

getSomething()
    .then(data => {
        console.log(data);
    })
    .catch(error => {
        console.log(error);
    });

ūüíĀ‚Äć‚ôÄÔłŹ El estilo para escribir el c√≥digo es algo personal, aunque hay ciertas convenciones. Normalmente, cuando encadenamos m√©todos, debemos ponerlos cada uno en una l√≠nea nueva para ser m√°s legibles. 


‚Äč‚ÄčPromises ‚Äčen la pr√°ctica‚Äč‚Äč

Hecho ya el ejemplo con datos simulados, vamos a utilizar promises para hacer una verdadera http request. Lo que vamos a hacer es utilizar una promise dentro de la funci√≥n getToDos(). Puedes comentar el ejemplo anterior para que no nos moleste.

1. Hacemos un return de una nueva promesa, que acepta una funci√≥n como par√°metro. Dentro de esta funci√≥n es donde haremos nuestra http request, as√≠ que cortamos el c√≥digo y lo pegamos ah√≠ dentro. 

2. Nuestra ‚Äčpromise ‚Äčacepta los m√©todos ‚Äčresolve ‚Äč‚Äčreject ‚Äčcomo par√°metros, as√≠ que se los pasamos. 

3. Ya no vamos a necesitar el segundo par√°metro en la funci√≥n getToDos (callbackFunc), as√≠ que lo eliminamos. Esto es as√≠ porque en lugar de llamar a la funci√≥n callbackFunc, vamos a llamar al m√©todo resolve o al reject seg√ļn la promesa se resuelva con √©xito o no. ūüôą

Al m√©todo ‚Äčresolve ‚Äčle pasamos la variable datamientras que al reject podemos pasarle un string diciendo que ha habido alg√ļn tipo de error, como hac√≠amos antes en nuestro ejemplo.

const getToDos = tasksList => {
    return new Promise((resolve, reject) => {
        const request = new XMLHttpRequest();

        request.addEventListener('readystatechange', () => {
            if (request.readyState === 4 && request.status === 200) {
                const data = JSON.parse(request.responseText);
                resolve(data);
            } else if (request.readyState === 4) {
                reject('no se han podido obtener los datos');
            }
        });

        request.open('GET', tasksList);
        request.send();
    });
};

4. Llamamos a la funci√≥n ‚ÄčgetToDos() ‚Äčy le pasamos un √ļnico par√°metro, el que hace referencia a la ‚ÄčtasksList. ‚ÄčLe pasamos por ejemplo el archivo JSON de Billy.

5. A la funci√≥n le adjuntamos el m√©todo ‚Äčthen(), ‚Äčque, como sabemos, est√° vinculado al m√©todo ‚Äčresolve(). ‚ÄčEs decir, la funci√≥n dentro de ‚Äčthen() ‚Äčse ejecutar√° si la ‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äčpromise ‚Äčse cumple. Le pedimos simplemente que haga un ‚Äčconsole.log ‚Äčde la informaci√≥n recibida en el ‚Äčresolve(). 

‚Äč‚Äč6. Hacemos lo mismo con el m√©todo ‚Äčcatch(), ‚Äčlo adjuntamos al ‚ÄčgetToDos ‚Äčy le pasamos una funci√≥n que simplemente ‚Äč‚Äč‚Äčimprima por consola el error que hemos especificado en el m√©todo ‚Äčreject() ‚Äčen caso de que algo salga mal. Recuerda que esta funci√≥n se disparar√° si algo sale mal en la promise y JS ejecuta el bloque de c√≥digo del m√©todo reject().‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč‚Äč

getToDos('toDos/billy.json')
    .then(data => {
        console.log('promise resolved!:', data);
    })
    .catch(error => {
        console.log('promise rejected :(', error);
    });

¬°Y ya est√°! ūüĎŹ Ahora en tu consola deber√≠as ver los datos de Billy. Si intentas escribir el API endpoint mal, por ejemplo:

getToDos('toDos/billyyyy.json')

JS ejecutar√° la parte del ‚Äčreject(), ‚Äčya que la promesa no se ha cumplido al no poder obtener los datos debido a un error por nuestra parte. ūüôÜ‚Äć‚ôÄÔłŹ

THE END!

¬°Y con esto terminamos nuestra segunda parte de esta Async saga! Espero que hayas aprendido algo nuevo ūüėä.  Si te queda alguna duda, ¬°nos vemos en los comentarios! 

‚Äč‚Äč‚ÄčSi quieres seguir aprendiendo, aqu√≠ tienes la parte #3.‚Äč‚Äč

Y si crees que este post puede serle √ļtil a alguien, ¬°comp√°rtelo!

Otros artículos que pueden interesarte

Guía de iniciación al data binding en Angular
¬ŅQu√© es el databinding?El databinding es la forma que tiene Angular para permitirnos mostrar contenido din√°mico en lugar de est√°tico (en ingl√©s, hardcoded). Podr√≠amos[...]
Días del 353 al 386
Objetivos versus realidad Y nuevamente, llegó otro día clave. Llegó…y pasó. El pasado 4 de marzo este Reto Computer Geek[...]
Angular: Entendiendo la Directiva ngModel
Angular es un framework que nos permite, entre otras cosas, a√Īadir contenido din√°mico a nuestros archivos HTML. Una de las formas[...]
Si crees que este post puede serle √ļtil a alguien, por favor, ¬°comp√°rtelo!:

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Como toda web legal que se precie, utilizamos cookies para asegurar que damos la mejor experiencia al usuario en nuestro sitio web. Si contin√ļas utilizando este sitio asumiremos que est√°s de acuerdo. m√°s informaci√≥n

Los ajustes de cookies de esta web están configurados para "permitir cookies" y así ofrecerte la mejor experiencia de navegación posible. Si sigues utilizando esta web sin cambiar tus ajustes de cookies o haces clic en "Aceptar" estarás dando tu consentimiento a esto.

Cerrar