Está en la página 1de 30

Cómo usar Fetch con async/await

Fetch API es la herramienta predeterminada para crear redes en aplicaciones


web. Aunque fetch()generalmente es fácil de usar, hay algunos matices a tener en cuenta.

En esta publicación, encontrará los escenarios comunes de cómo


usar fetch()con async/awaitsintaxis. Comprenderá cómo recuperar datos, manejar errores de
recuperación, cancelar una solicitud de recuperación y más.

Tabla de contenido
 1. Introducción a buscar()
 2. Obtener JSON
 3. Manejo de errores de recuperación
 4. Cancelación de una solicitud de recuperación
 5. Solicitudes de recuperación paralelas
 6. Resumen
1. Introducción a buscar()

La API Fetch accede a los recursos a través de la red. Puede realizar solicitudes HTTP
(utilizando GETy POSTotros métodos), descargar y cargar archivos.

Para iniciar una solicitud, llame a la función especial fetch():

const response = await fetch(resource[, options]);

que acepta 2 argumentos:

 resource: la cadena de URL o un objeto de solicitud


 options: el objeto de configuración con propiedades como method, headers, body, credentialsy más .

fetch() una solicitud y devuelve una promesa. Cuando se completa la solicitud, la promesa se resuelve con el
objeto Respuesta . Si la solicitud falla debido a algunos problemas de red, se rechaza la promesa.

async/await la sintaxis encaja muy fetch()bien porque simplifica el trabajo con promesas.

Por ejemplo, hagamos una solicitud para buscar algunas películas:

async function fetchMovies() {


const response = await fetch('/movies');
// waits until the request completes...
console.log(response);
}
fetchMovies() es una función asíncrona ya que está marcada con la asyncpalabra
clave.
await fetch('/movies')inicia una solicitud HTTP a la '/movies'URL. Debido a que
la awaitpalabra clave está presente, la función asíncrona se detiene hasta que se
completa la solicitud.
Cuando se completa la solicitud, responsese le asigna el objeto de respuesta de la
solicitud. Veamos en la siguiente sección cómo extraer datos útiles, como JSON
o texto sin formato, de la respuesta.
2. Obtener JSON

El responseobjeto, devuelto por await fetch(), es un marcador de posición


genérico para múltiples formatos de datos.
Por ejemplo, puede extraer el objeto JSON de una respuesta de búsqueda:
async function fetchMoviesJSON() {
const response = await fetch('/movies');
const movies = await response.json();
return movies;
}
fetchMoviesJSON().then(movies => {
movies; // fetched movies
});

es un método en el objeto Response que le permite extraer un


response.json()
objeto JSON de la respuesta. El método devuelve una promesa, por lo que debe
esperar el JSON: await response.json().
El objeto Response ofrece una gran cantidad de métodos útiles (todas las
promesas de retorno):
 response.json()devuelve una promesa resuelta a un objeto JSON
 response.text()devuelve una promesa resuelta a texto sin formato
 response.formData()devuelve una promesa resuelta a FormData
 response.blob()devuelve una promesa resuelta a un Blob (un objeto similar a
un archivo de datos sin procesar)
 devuelve una promesa resuelta a
response.arrayBuffer()()
un ArryBuffer (datos binarios genéricos sin procesar)
3. Manejo de errores de recuperación

Cuando me estaba familiarizando con fetch(), me sorprendió que fetch()no


arroje un error cuando el servidor devuelve un estado HTTP incorrecto, por
ejemplo, 400–499errores de cliente ( ) o servidor ( 500–599).
Por ejemplo, accedamos a una página que no existe '/oops'en el servidor. Como
era de esperar, dicha solicitud termina en un 404estado de respuesta:
async function fetchMovies404() {
const response = await fetch('/oops');

response.ok; // => false


response.status; // => 404
const text = await response.text();
return text;
}
fetchMovies404().then(text => {
text; // => 'Page not found'
});

Al obtener la URL '/oops', el servidor responde con el estado 404y el texto 'Page


not found'. Sorprendentemente, fetch()no arroja un error por una URL faltante,
sino que lo considera como una solicitud HTTP completa .
rechaza solo si no se puede realizar una solicitud o no se puede recuperar
fetch()
una respuesta. Puede ocurrir debido a problemas de red: no hay conexión a
Internet, no se encuentra el host, el servidor no responde.
Afortunadamente, response.okla propiedad le permite separar los estados de
respuesta HTTP buenos de los malos. La propiedad se establece en truesolo si la
respuesta tiene estado 200-299.
En el ejemplo anterior, la response.okpropiedad se falsedebe a que la respuesta
tiene el estado 404.
Si desea generar un error en un estado HTTP incorrecto (fuera del rango 200-299),
verifique el valor de la response.okpropiedad y genere un error manualmente:
async function fetchMoviesBadStatus() {
const response = await fetch('/oops');
if (!response.ok) {
const message = `An error has occured: ${response.status}`;
throw new Error(message);
}
const movies = await response.json();
return movies;
}
fetchMoviesBadStatus().catch(error => {
error.message; // 'An error has occurred: 404'
});

4. Cancelación de una solicitud de recuperación

Desafortunadamente, fetch()la API por sí sola no permite cancelar una solicitud


de recuperación una vez iniciada. Para cancelar una solicitud de recuperación,
necesita una herramienta adicional AbortController .
Conexión fetch()y AbortControllerrequiere 3 pasos:
// Step 1: instantiate the abort controller
const controller = new AbortController();
// Step 2: make the fetch() aware of controller.signal
fetch(..., { signal: controller.signal });
// Step 3: call to cancel the request
controller.abort();

A) Antes de iniciar la solicitud, cree una instancia de controlador de


cancelación: controller = new AbortController().
B) Al iniciar la solicitud correctamente, use el argumento de opciones fetch(url,
{ signal: controller.signal })y establezca la signalpropiedad en controller.signal.

C) Finalmente, si necesita cancelar la solicitud, simplemente llame


al controller.abort()método.
Por ejemplo, implementemos 2 botones que controlen una solicitud de
recuperación. Al hacer clic en el botón Recuperar películas , se inicia
una fetch()solicitud, mientras que al hacer clic en Cancelar recuperación , se
cancela la solicitud en curso:
let controller = null;
fetchMoviesButton.addEventListener('click', async () => {
controller = new AbortController();
try {
const response = await fetch('/movies', {
signal: controller.signal
});
} catch (error) {
console.log('Fetch error: ', error);
}
controller = null;
});
cancelFetchButton.addEventListener('click', () => {
if (controller) {
controller.abort();
}
});

Abre la demostración . Haga clic en Obtener películas para iniciar la solicitud,


luego haga clic en Cancelar obtención para cancelarla. Esto hace que la solicitud
activa se cancele: await fetch()se rechaza arrojando un error de
cancelación. Luego, el catchbloque detecta el error de cancelación.
Las instancias del controlador de cancelación no son reutilizables. Cada vez que
inicia una fetch()solicitud, debe crear una nueva instancia de controlador de
cancelación para cada solicitud.
En una nota al margen, si desea que se agote el tiempo de espera de
una fetch()solicitud, siga mi publicación Cómo agotar el tiempo de espera de
una solicitud fetch() .
5. Solicitudes de recuperación paralelas

Para realizar solicitudes de recuperación paralelas, use la función


auxiliar Promise.all() .
Comencemos 2 solicitudes paralelas para obtener películas y categorías:
Abre la demostración . Haga clic en Obtener películas para iniciar la solicitud,
luego haga clic en Cancelar obtención para cancelarla. Esto hace que la solicitud
activa se cancele: await fetch()se rechaza arrojando un error de
cancelación. Luego, el catchbloque detecta el error de cancelación.
Las instancias del controlador de cancelación no son reutilizables. Cada vez que
inicia una fetch()solicitud, debe crear una nueva instancia de controlador de
cancelación para cada solicitud.
En una nota al margen, si desea que se agote el tiempo de espera de
una fetch()solicitud, siga mi publicación Cómo agotar el tiempo de espera de
una solicitud fetch() .
5. Solicitudes de recuperación paralelas

Para realizar solicitudes de recuperación paralelas, use la función


auxiliar Promise.all() .
Comencemos 2 solicitudes paralelas para obtener películas y categorías:
await Promise.all([...]) comienza a buscar solicitudes en paralelo y espera hasta
que se resuelvan todas.
Si alguna solicitud falla, toda la promesa paralela se rechaza de inmediato con el
error de solicitud fallida.
En caso de que desee que se completen todas las solicitudes paralelas, a pesar de
que alguna de ellas falle, considere usar Promise.allSettled() .
6. Resumen

La llamada fetch()inicia una solicitud y devuelve una promesa. Cuando se


completa la solicitud, la promesa se resuelve en el objeto de respuesta. Del objeto
de respuesta puede extraer datos en el formato que necesite: JSON, texto sin
formato, Blob.
Debido a que fetch()devuelve una promesa, puede simplificar el código usando
la async/awaitsintaxis: response = await fetch().
Averiguó cómo usar fetch()acompañado async/awaitpara obtener datos JSON,
manejar errores de obtención, cancelar una solicitud, realizar solicitudes
paralelas.
Habiendo dominado los conceptos básicos de fetch()with async/await, siga mi
publicación sobre Cómo agotar el tiempo de espera de una solicitud fetch() .

Cómo agotar el tiempo de espera


de una solicitud fetch()
Cuando se desarrolla una aplicación que usa la red, la primera regla a recordar
es no confiar en la red .
La red no es confiable porque una solicitud o respuesta HTTP puede fallar por
muchas razones:
 El usuario está desconectado
 La búsqueda de DNS falló
 El servidor no responde
 El servidor responde pero con un error.
 y más.
Los usuarios pueden esperar hasta 8 segundos para que se completen las
solicitudes simples. Es por eso que debe establecer un tiempo de espera en las
solicitudes de la red e informar al usuario después de 8 segundos sobre los
problemas de la red.
Le mostraré cómo usar setTimeout(), el controlador de cancelación y fetch()la
API para realizar solicitudes con un tiempo de espera configurable (¡se incluyen
demostraciones interesantes!).
1. Tiempo de espera predeterminado de fetch()

Por defecto, una fetch()solicitud expira en el momento indicado por el


navegador. En Chrome, un tiempo de espera de solicitud de red es de 300
segundos, mientras que en Firefox es de 90 segundos.
async function loadGames() {
const response = await fetch('/games');
// fetch() timeouts at 300 seconds in Chrome
const games = await response.json();
return games;
}

300 segundos e incluso 90 segundos son mucho más de lo que un usuario


esperaría que completara una simple solicitud de red.
En la demostración , la /gamesURL se configuró para responder en 301
segundos. Haga clic en el botón Cargar juegos para iniciar la solicitud y se
agotará el tiempo de espera a los 300 segundos (en Chrome).
2. Tiempo de espera de una solicitud fetch()

La API por sí sola no permite cancelar una solicitud mediante


fetch()
programación. Para detener una solicitud en el momento deseado, necesita
además un controlador de cancelación .
La siguiente fetchWithTimeout()es una versión mejorada de fetch()que crea
solicitudes con un tiempo de espera configurable:
async function fetchWithTimeout(resource, options = {}) {
const { timeout = 8000 } = options;

const controller = new AbortController();


const id = setTimeout(() => controller.abort(), timeout);
const response = await fetch(resource, {
...options,
signal: controller.signal
});
clearTimeout(id);
return response;
}

Primero, const { timeout = 8000 } = optionsextrae el parámetro de tiempo de


espera en milisegundos del optionsobjeto (el valor predeterminado es 8
segundos).
crea una instancia del controlador de
const controller = new AbortController()
aborto . Este controlador le permite detener fetch()las solicitudes a
voluntad. Tenga en cuenta que para cada solicitud se debe crear un nuevo
control de cancelación, en otras palabras, los controladores no son reutilizables.
const id = setTimeout(() => controller.abort(), timeout)inicia una función de
temporización. Después timeoutde un tiempo, si la función de temporización no
se borró, abortará controller.abort()(o cancelará) la solicitud de recuperación.
La siguiente línea await fetch(resource, { ...option, signal:
controller.signal })inicia correctamente la solicitud de recuperación. Tenga en
cuenta el controller.signalvalor especial asignado a la signalpropiedad: se
conecta fetch()con el controlador de cancelación.
Finalmente, clearTimeout(id)borra la función de tiempo de cancelación si la
solicitud se completa más rápido que el timeouttiempo.
Ahora aquí está cómo usar fetchWithTimeout():
async function loadGames() {
try {
const response = await fetchWithTimeout('/games', {
timeout: 6000
});
const games = await response.json();
return games;
} catch (error) {
// Timeouts if the request takes
// longer than 6 seconds
console.log(error.name === 'AbortError');
}
}

(en lugar de simple fetch()) inicia una solicitud que se cancela


fetchWithTimeout()
en el timeouttiempo — 6 segundos.
Si la solicitud /gamesno finaliza en 6 segundos, se cancela y se genera un error de
tiempo de espera.
Puede usar la expresión error.name === 'AbortError'dentro del catchbloque para
determinar si hubo un tiempo de espera de solicitud.
Abra la demostración y haga clic en el botón Cargar juegos . La solicitud
se /gamesagota porque tarda más de 6 segundos.
3. Resumen

De forma predeterminada, una fetch()solicitud se agota en el momento en que


lo configura el navegador. En Chrome, por ejemplo, esta configuración equivale
a 300 segundos. Eso es mucho más tiempo de lo que un usuario esperaría para
completar una solicitud de red simple.
Un buen enfoque al realizar solicitudes de red es configurar un tiempo de espera
de solicitud de aproximadamente 8 a 10 segundos.
Como se muestra en la publicación, al usar setTimeout()y abortar el controlador
puede crear fetch()solicitudes configuradas para el tiempo de espera cuando lo
desee.
Verifique el soporte del navegador del controlador de aborto porque a partir de
2020 es una tecnología experimental. También hay un polyfill para ello.
Tenga en cuenta que sin el uso de un controlador de cancelación no hay forma
de detener una fetch()solicitud. No utilice soluciones como esta .

El método fetch()
El método fetch de la nueva API fetch busca y trae recursos como datos, imágenes etc. . . de
otros archivos ( fetch significa ir a buscar algo, traer algo ).
Un ejemplo básico: utilizar la función fetch para traer una imagen .jpg y mostrarla en pantalla.

// la función fetch toma un solo argumento: la ruta hacia la imagen


fetch('imagen.jpg')
//una vez llamada la función fetch tenemos que esperar una respuesta, y la
respuesta es parte de una promesa.
// si hay una respuesta devuélvemela en forma de (texto o en forma de json, o
en forma de) blob...
.then(respuesta =>{
return respuesta.blob();
})
// de nuevo necesitamos esperar el blob y cuando lo tenemos
.then(respuesta2=>{
// utilizamos el método URL.createObjectURL() para crear una cadena de texto
que puede ser utilizada como valor del atributo src de una imagen
fetchTest.src = URL.createObjectURL(respuesta2)
})
// pero si hay algún error atrápalo (catch)
.catch(error =>{console.error(error)})

Vea este ejemplo en codepen:

<img src="" id="fetchTest" />


<p id="output"></p>

<img src="" id="fetchTest" />


<p id="output"></p>

La palabra clave await


Podemos hacer lo mismo utilizando la palabra clave async. En este caso el codigo es más
conciso y presuntamente más facil de leer

La palabra clave await puede ser utilizada solamente en funciones asíncronas, Empleamos la


palabra clave async para especificar que una función se ejecuta de manera asíncrona.

Primero necesitamos crear una función asíncrona

async function funcionAsincrona(url){


// espera (await) una respuesta de fetch()
const  respuesta = await fetch(url);
// espera (await) el blob
const respuesta2= await response.blob();
// y cuando lo tenga crea un nuevo objeto url y utilízalo como valor del
atributo src de la imagen
fetchTest.src = URL.createObjectURL(blob)
}

A continuación podemos llamar la funcionAsincrona()

//Pero en el caso en el cual hay un error atrápalo con catch


funcionAsincrona().catch(error =>{console.error(error)})
Vea este ejemplo en codepen:
<img src="" id="fetchTest" />

let url = "https://s.cdpn.io/profiles/user/222579/80.jpg";

funcionAsincrona(url)
// en el caso de exito
.then(console.log("ya tengo la imagen!!"))
// en caso de error
.catch(error =>{console.error(error)})

async function funcionAsincrona(url){


const response = await fetch(url);
const blob = await response.blob();
fetchTest.src = URL.createObjectURL(blob)
}

Fetch API, la guia completa para hacer


llamadas HTTP en javascript y olvidarte de
axios
Javascript •14 de abr. de 2020

Con la llegada del es6 para javascript, surgieron nuevas características que facilitaron el uso del
lenguaje en tareas que anteriormente hicieron a muchos desarrolladores orientarse por
utilizar JQuery, como las peticiones HTTP, sin embargo ha pasado el tiempo y las webapps
modernas necesitan nuevas herramientas potentes, y esa es la razón para mirar hacia Fetch API,
tanto así probablemente no necesites más de Jquery ni de axios ni de ninguna otra herramienta
más al terminar de leer esta entrada, así que acomódate bien y acompáñame en las siguientes
líneas donde detallaré todo este tema.
Tiempos memoriales de XMLHttpRequest

Recuerdo que hace algunos años, solo tenias dos opciones para hacer peticiones HTTP,
eran XMLHttpRequest puro y duro o solicitudes AJAX de JQuery para abreviar el mismo
proceso, pero es más, incluso habían y hay aún desarrolladores que realizan el siguiente proceso:
primero aprenden a realizar peticiones utilizando XHR y luego debido a la simplicidad decían:
"para ya no demorar mejor JQuery", y sabes que...en parte tienen razón, porque en muchos casos
es necesario realizar un proyecto de forma rápida, o para un prototipo que no necesita mayor
complicación, pero en otros casos donde la performance y peso de la aplicación es importante
pensando a largo plazo, es mejor evitar utilizar todo el paquete completo que trae JQuery.

Pero como ningún mal dura 100 años, ahora tenemos disponible a Fetch API, una característica
que viene a aportar cosas interesantes, continuemos...

Fetch API

Básicamente es una API de javascript que a través de su interfaz te permite realizar  peticiones
HTTP para obtener recursos de la red, globalmente expone un objeto del lado del navegador
llamado fetch. Déjame contarte que desde el inicio, cuando recién salió en forma experimental
ésta característica se notó flexible, esto empezó a llamar la atención de gran cantidad de
desarrolladores, y luego con el paso del tiempo, con multiples cambios realizados a lo largo de los
años se ha vuelto más robusta.

¿Por qué elegir Fetch API sobre axios o request?

Buenas pregunta, sin embargo cuando miramos las comparaciones puedes tener datos
sumamente reveladores.
Comparación fetch vs axios vs request

Interceptar solicitudes y respuestas, trasformar esos mismos datos y la cancelación de


solicitudes son las 3 primeras características que personalmente enamoran, por otro lado,
poder ver el progreso de tu solicitud y streaming   de datos en fetch son cosas que simplemente
hacen explotar tu imaginación.

Si bien la mayoría de las características están disponibles también en sus competidores directos
(axios y request ), la gran ventaja de fetch es que no necesitas agregar ninguna dependencia de
terceros para poder hacer lo mismo...entonces...¿tú que eliges?... te dejo con esa pregunta mente,
ahora vamos a meter las manos en la masa.

Flujo básico de fetch

Fetch tiene un proceso de solicitud super sencillo de entender:

1. Realizas la solicitud.

2. Devuelve una promesa, que resuelve un objeto Response.

3. El objeto response es leído a través de funciones según el tipo de dato (json, blob, text, etc.).

Sintaxis estándar de solicitud

La sintaxis básica para realizar peticiones es la siguiente:

fetch(url) // 1
.then(response => response.json()) // 2

.then(console.log) // 3

.catch(console.log('Algo salió mal.'));

Sintaxis solicitud fetch

La ventaja de utilizar promesas es que estas nos permiten encadenarlas, de tal forma que el
resultado de una promesa es pasado como parámetro hacia la siguiente promesa, a menos que se
produzca un error y se pase directamente hacia una función catch(), con eso en mente tenemos las
siguientes instrucciones:

1. Realiza la solicitud a una determinada URL.

2. Resuelve la promesa, al obtener respuesta la pasa a un determinado formato utilizando la función


correspondiente, en este caso JSON.

3. Lee el objeto data y lo imprime con un console.log().

4. Si hay un error es atrapado por la función catch.

Ejemplo básico

Bien, ahora materializamos el ejemplo realizando una solicitud super básica hacia la API
de jsonplaceholder.

fetch('https://jsonplaceholder.typicode.com/todos/1') // 1

.then(response => response.json()) // 2

.then(console.log); // 3

// {"userId":1,"id":1,"title":"delectus aut autem","completed":false}

Ejemplo básico

Detallamos el proceso de la siguiente manera:


1. Realizamos la solicitud a la API de jsonplaceholder (esa función devuelve una promesa).

2. La promesa es resuelta gracias al then(), que tiene una función espera un objeto Response, y ese
objeto nos permite usar la función json() para resolver la data que viene en ese formato (esa función
devuelve una promesa - otra vez).

3. La segunda promesa es resuelta con el segundo then(), y es pasada al console.log (que también es


una función y espera N parámetros) para imprimir el resultado.

Realizando una solicitud / petición

Aquí es donde inicia la magia y fetch provee una forma de configurar fácilmente las opciones que
necesitas asignar para realizar tus peticiones, muchos de estos son opcionales según el tipo de
solicitud, veamos algunas:

 method: Método de la solicitud, por ejemplo GET, POST, PUT, OPTIONS, DELETE, etc.

 headers: Cabeceras que se envían en la solicitud, aquí puedes ingresar un objeto e incluso una
instancia de Headers.

 body: Datos para enviar en la solicitud, pueden ser un blob, un buffer, form data, string,
etc...considera que las solicitudes GET y HEAD no utilizan esta opción.

 mode: Modo de envío de la solicitud, puede ser cors, no-cors o  same-origin.

 credentials: Credenciales que utiliza la petición. 

 cache: Indica cómo se debe comportar la solicitud con el cache del navegador.

 redirect: Cómo debe actuar si la respuesta devuelve una redirección.

Solicitud GET con Fetch

Es la petición más básica que debes aprender a realizar, este tipo de peticiones es utilizada para
obtener información, el siguiente ejemplo trae una lista de objetos:

fetch('https://jsonplaceholder.typicode.com/todos')

.then(response => response.json())


.then(console.log);

// [{}, {}, {}, ...]

Solicitud GET con Fetch

Solicitud POST con Fetch

La siguiente petición es para enviar información a un servidor, puedes realizarla de la siguiente


manera:

fetch("https://reqres.in/api/users", {

method: "POST",

body: JSON.stringify({ website: "eldevsin.site" })

})

.then(response => response.json())

.then(console.log);

// {id: "370", createdAt: "2020-04-13T03:40:09.969Z"}

Solicitud POST con Fetch

Nótese que hemos agregado la key body, es allí donde podemos agregar la data que se enviara al
server, en este caso en particular está todo ok y la API nos devuelve como respuesta un objeto
ficticio.

Utilizando Headers en la petición

Cuando realizas una petición es muy común que necesites personalizar la cabecera, y fetch te
permite hacerlo de una manera super simple utilizando una instancia de Header, veamos:
const customHeaders = new Headers({

'User-agent': 'Mozilla/5.0 (PlayStation 4 3.11) AppleWebKit/537.73


(KHTML, like Gecko)'

});

/*

-> lo de arriba es lo mismo que esto:

const customHeaders = {

'User-agent': 'Mozilla/5.0 (PlayStation 4 3.11) AppleWebKit/537.73


(KHTML, like Gecko)'

};

*/

fetch('https://jsonplaceholder.typicode.com/todos', {

headers: customHeaders

})

.then(response => response.json())

.then(console.log);

Headers en la solicitud Fetch

Como puedes ver estamos simulando realizar la petición desde un playstation, pero aún mas
importante que eso es que puedes utilizar un objeto literal para construir un header, ¿genial no?
Enviando un form data con fetch

Este es un caso super utilizado y que con seguridad tú también lo necesitarás en algún momento
de tu vida como desarrollador, el diferencial aquí es el dato que enviamos al backend en el body
de las opciones.

const formData = new FormData();

formData.append('website', 'elsitesin.site');

formData.append('action', 'follow');

fetch('urldeapi/create', {

method: 'POST',

body: formData // mira abajo la explicación :D

})

.then(response => response.json())

.then(console.log);

Enviando Form Data con Fetch

Esta forma de enviar información se utiliza cuando envías por ejemplo una imagen, un video o
incluso solo texto cuando tienes la información dentro de la etiqueta form, lo bueno de todo es
que FormData te permite apilar la información en forma de clave y valor.

Ahora, quizás de has dado cuenta de que no estamos especificando el tipo de contenido que
enviamos, es decir el Content-Type, la razón en este caso puntualmente es que no es necesario,
porque es agregado automáticamente al header, el tipo de contenido viaja como
"multipart/form-data".
Enviando credenciales en fetch

Este es un caso de uso de igual forma de común cuando necesitas identificar a tus usuarios, por
fortuna es una característica que está disponible en fetch y solo basta con agregar una línea para
indicarle si queremos que incluya cookies en la petición, literalmente:

fetch('https://jsonplaceholder.typicode.com/todos', {

credentials: 'include'

})

.then(response => response.json())

.then(console.log);

Credenciales en Fetch

La especificación lo deja muy claro, veamos todas las opciones:

 include: Envía la cookie a cualquier origen de datos, es decir aquí no importa en qué dominio se
ejecuta esta acción.

 same-origin: Envía la petición solo si el host solicitado coincide con el origen desde donde se esta
ejecutando el script.

 omit: Por ningún motivo se envían las credenciales.

Configurar CORS en fetch API

CORS viene a ser una característica que resuelve en muchos casos el problema de realizar
solicitudes a dominios desconocidos, vulnerabilidades que normalmente son aprovechados por
piratas informáticos. A través de la opción mode puedes modificar el comportamiento:

fetch('https://jsonplaceholder.typicode.com/todos', {

mode: 'cors'

})
.then(response => response.json())

.then(console.log);

CORS en Fetch API

La configuración que definas aquí puede resultar crítico cuando solicitas recursos de otros
dominios, por eso ten en cuenta las siguientes opciones:

 cors: Permite realizar peticiones hacia cualquier origen.

 no-cors: Permite realizar solicitudes hacia cualquier origen sin embargo la respuesta se oculta para
impedir visualizar lo que viene como información.

 same-origin: Permite realizar las solicitudes hacia el mismo dominio, caso contrario recibes más
que seguro un error.

Te cuento algo, muy aparte de poder utilizar esas opciones, tienes la facilidad de poder pasarle a
fetch tu propio objeto de Request, de la siguiente forma:

const myConfig = {

headers: {

'Content-Type': 'application/json'

const request = new Request(

'https://jsonplaceholder.typicode.com/todos',

myConfig

);
fetch(request)

.then(response => response.json())

.then(console.log)

Objeto Request en Fetch API

A eso es que no referíamos con la flexibilidad, considéralo cuando necesites realizar algo similar
en tus proyectos web.

Respuesta

El objeto de respuesta básicamente en un objeto del tipo Response , que trae consigo


características interesantes para quien sepa aprovecharlas, pues además proporciona gran
cantidad de funciones para tratar los tipos de respuesta.

Utilizando la siguiente request como ejemplo:

fetch("https://jsonplaceholder.typicode.com/todos")

.then(response => console.log(response));

Ejemplo básico

La estructura del objeto que recibes como respuesta es la siguiente:

type: "cors"

url: "https://jsonplaceholder.typicode.com/todos"

redirected: false

status: 200
ok: true

statusText: ""

headers: Headers {}

body: (...)

bodyUsed: false

Estructura de objeto Response

La mayoría del tiempo solo considerarás utilizar las siguientes propiedades:

 redirected: Indica si la respuesta que obtienes fue hecha por una redirección.

 status: Código de estado HTTP.

 ok: Devuelve un booleano con un true/false para indicar si la respuesta fue exitosa o no.

 headers: Cabeceras devueltas.

 body: Información enviada por el servidor del tipo ReadableStream.

 bodyUsed: Indica si la información del body ya fue leída o no.

¿Cómo leer el contenido del body?

Como lo mencionamos anteriormente, obtenemos una respuesta de una instancia del tipo
Response, por lo que tenemos acceso a ciertos métodos que nos resuelven la información de
acuerdo al tipo de dato que vamos a obtener.

En nuestro ejemplo básico tenemos lo siguiente:

fetch("https://jsonplaceholder.typicode.com/todos/1")

.then(response => response.json())


.then(console.log)

Ejemplo básico

Se apreciar muy bien que ejecutamos la función .json(), que obviamente indica que la data que
queremos ver es de tipo JSON, y devuelve una promesa que debe completarse hasta que termine
de formatear la información llegada del backend, el resultado debe ser similar a lo siguiente:

{userId: 1, id: 1, title: "delectus aut autem", completed: false}

Respuesta de ejemplo

Pero esa no es la única función que tenemos disponible, existen otras más que debes conocer y
que te ahorrarán muchos dolores de cabeza en el futuro:

 clone(): Devuelve una copia del objeto Response.

 blob(): Devuelve una promesa y al terminar de obtener la información del servidor resuelve un


objeto del tipo Blob .

 json(): Devuelve una promesa y al terminar de obtener la información del servidor resuelve un


objeto del tipo JSON.

 text(): Devuelve una promesa y al terminar de obtener la información del servidor resuelve un


objeto del tipo TEXT .

 arrayBuffer(): Devuelve una promesa y al terminar de obtener la información del servidor resuelve


un objeto del tipo ArrayBuffer .

 formData(): Devuelve una promesa y al terminar de obtener la información del servidor resuelve


un objeto del tipo FormData .

Ejemplo para monitorear el progreso de una solicitud

Por motivos de usabilidad es primordial informar al usuario cual es el porcentaje de


progreso que va completando una solicitud, sobretodo si es que estamos mostrando recursos
como imágenes, vamos a ver un ejemplo sencillo de como podemos monitorear el avance de una
solicitud utilizando la instancia de la clase ReadableStreams .
Definiendo el lector de progreso

Esta función debe permitir dos cosas, primero, recibir una función que será ejecutada cafa vez que
se recibe trozos de información y segundo, nos permita manipular el objeto Response.

function progressReader(onProgress) { // 1

return response => { // 2

if (!response.body) return response;

let loaded = 0;

const contentLength = response.headers.get("content-length"); // 3

const total = !contentLength ? -1 : parseInt(contentLength, 10);

const readable = new ReadableStream({

start(controller) {

const reader = response.body.getReader(); // 4

read(); // 5

function read() {

return reader

.read() // 6

.then(({ done, value }) => {


if (done) return controller.close(); // 7

loaded += value.byteLength;

onProgress({ loaded, total }); // 8

controller.enqueue(value);

return read(); // 9

})

.catch(error => {

console.error(error);

controller.error(error);

});

});

return new Response(readable); // 10

};

Lector de progreso solicitud Fetch

El proceso es un poco complejo, así que lo dividiremos en dos partes.

Primero revisamos los pasos que tienen que ver con la forma que construimos la función.
1. Declaramos una función que espera un callback que servirá para notificar cada vez que reciba un
trozo de información.

2. Devuelve un closure que se usará para al momento que se resuelve la promesa, esta recibirá el
objeto Response.

3. Obtenemos la longitud del contenido de la imagen.

La siguiente parte ya va un poco más a lo duro del ejercicio, jugar con Streams, vamos a intentar
hacerlo simple y entendible, para eso considera que el constructor del objeto ReadableStream,
espera que le pases un objeto con ciertas opciones, en este caso, usaremos clave start para
configurar cómo queremos que se comporte el lector de streams.

4.  Obtenemos el lector de streams.

5.  Ejecutamos por primera vez la función personalizada que empezará a leer los trozos de datos.

6.  La función read() retorna una promesa que se resuelve cuando se recibe información. Al


ejecutar nuestra función nos envían dos parámetros done(si ya termino de leer) y value(trozo de
información).

7.  Si la información se ha terminado de leer, entonces "cierra el caño", es decir, indicar que la
transmisión concluyó.

8.  Enviamos al console.log la cantidad de datos leídos hasta el momento y el total de datos de la


imagen.

9.  Ejecuta nuevamente read() para recibir el siguiente trozo de información, y repite el proceso


hasta que ya no tenga más datos que recibir y caiga en el punto 7.

10.  Devuelve un objeto Response con el reader que acabamos de configurar.

Con eso ya estamos listos para implementarlo en nuestras solicitudes con fetch, sigamos con la
siguiente parte:

Inyectanto el lector de Streams

const streamProcessor = progressReader(console.log); // 11


fetch("https://fetch-progress.anthum.com/20kbps/images/sunrise-
progressive.jpg")

.then(streamProcessor) // 12

.then(response => response.blob()) // 13

.then(blobData => {

// Blob data

});

Inyectando lector de Streams

11. Ejecutamos la función progressReader que acabamos de crear y le pasamos console.log(que


recuerda que también es una función), esta se encargará de informarnos el porcentaje de avance
cada vez que un trozo de información es recibido, esta nos devolverá a su vez una nueva función
que por ahora se almacena en la variable streamProcessor.

12. "Inyectamos" streamProcessor en el primer then() para que reciba un objeto response y


devuelva nuestro objeto Response (ya modificado).

13. Finalmente como esperamos un recurso de tipo imagen, debemos utilizar la


función blob() para leer dicha información.

Después de eso ya tienes disponible el recurso para insertarlo en cualquier parte de tu frontend.

Response

for(var i = 0; i < arrInput.length; i++){


if (arrInput[i].type == "button") {
// The current element is button
}
}

function GetAllRadioButtons() {
var arrInput = document.getElementsByTagName("input"), arrRadio = new Array();
var j = 0;
for (var i = 0; i < arrInput.length; i++) {
if (arrInput[i].type == "radio") {
arrRadio[j] = arrInput[i];
j++;
}
}
return arrRadio;
}

function GetAllSelectRadioButtons() {
var arrInput = document.getElementsByTagName("input"), arrRadio = [];
var j = 0;
for (var i = 0; i < arrInput.length; i++) {
if (arrInput[i].type == "radio" && arrInput[i].checked) {
arrRadio[j] = arrInput[i];
j++;
}
}
return arrRadio;
}

var arrA = document.getElementsByTagName("a");

var matches = [];

var inputs = document.getElementsByTagName('input');

for(var key in inputs) {


var value = inputs[key].value;

if(value === '07') {


matches.push(value);
}
}

function getInputs() {
var matches = [];

var inputs = document.querySelectorAll('input');

for(var i = 0; i < inputs.length; i++) {


var value = inputs[i].value;

if(value === '07') {


matches.push(value);
}
}
console.log(matches);
}

const form = document.getElementById('form');


console.log(form.elements);

[...form.elements].forEach((item) => {
console.log(item);
});

También podría gustarte